C/C++ Extern Function call fails to pass parameter by value [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 days ago.
Improve this question
I have a "legacy" app that uses the following C compiler:
c:\Development\Source\HighSpeedQuote2022\bin>cl /?
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
I use the above line of batch code to compile it.
That MAKE.BAT file creates a piece of the app and produces a C DLL that is eventually called by a VB6 front end. My problem centers around some initialization code called internally within the C DLL that sends an index variable (passed by value) to an extern function call that fails to pass the parameter's value. I'm developing on a Win7 box as well.
Here are the code excerpts:
HsCalc6.c function prototype:
void InitCommonGrData();
Rating6.c function prototype:
extern void SaveGearAPI613Data(double n1 , double b , double dw1, int ZE , double ZI , double ZN, double Kv , double KH , double kHP,
double CSF, double SigmaHP, double Pd , double YJ , double SigmaFP, double YN, double KSF, double kFP, int YL ,
double bod, double KHpf , double Paz, double Pay, int ix , int dummy);
The calling code is within HsCalc6.InitCommonGrData:
for(ix=ix_PINION;ix<=ix_GEAR;ix++)
{
ConvertMsg(ix,"ix = ");
AddLogEntry(moduleName,"InitCommonGrData",msg);
if(ix==ix_PINION) ConvertMsgC("PINION","SaveGearAPI613Data for ");
if(ix==ix_GEAR) ConvertMsgC("GEAR","SaveGearAPI613Data for ");
AddLogEntry(moduleName,"InitCommonGrData",msg);
AddLogEntry(moduleName,"InitCommonGrData","Dummy=58");
// 0 1 2 3 4 5 6 7 8 9
SaveGearAPI613Data(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
// 0 1 2 3 4 5 6 7 8
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
// 9 0 1 2 3
0.0,0.0,0.0,0.0,**ix**, 58);
// See RATING6.C for above call
}
AddLogEntry(moduleName,"InitCommonGrData","Exit");
}
The external function resides in Rating6.SaveGearAPI613Data and is shown here:
extern void SaveGearAPI613Data( double n1 , double b , double dw1, int ZE , double ZI , double ZN, double Kv , double KH , double kHP,
// 0 1 2 3 4 5 6 7 8
double CSF, double SigmaHP, double Pd , double YJ , double SigmaFP, double YN, double KSF, double kFP, int YL ,
// 9 0 1 2 3
double bod, double KHpf , double Paz, double Pay, int ix, int dummy)
{
AddLogEntry(moduleName,"SaveGearAPI613Data","Entry");
ConvertMsg(ix,"ix = ");
AddLogEntry(moduleName,"SaveGearAPI613Data",msg);
if (ix == ix_PINION) {
AddLogEntry(moduleName,"SaveGearAPI613Data","Saving PINION data...");
GrA->A613[ix].HT = Gr->HeatTreat[ix_PINION].i; }
else if(ix == ix_GEAR) {
AddLogEntry(moduleName,"SaveGearAPI613Data","Saving GEAR data...");
GrA->A613[ix].HT = Gr->HeatTreat[ix_GEAR].i; }
GrA->A613[ix].n1 = n1;
GrA->A613[ix].b = b;
GrA->A613[ix].dw1 = dw1;
GrA->A613[ix].ZE = ZE;
GrA->A613[ix].ZI = ZI;
GrA->A613[ix].ZN = ZN;
GrA->A613[ix].Kv = Kv;
GrA->A613[ix].KH = KH;
GrA->A613[ix].kHP = kHP;
GrA->A613[ix].CSF = CSF;
GrA->A613[ix].SigmaHP = SigmaHP;
GrA->A613[ix].Pd = Pd;
GrA->A613[ix].YJ = YJ;
GrA->A613[ix].SigmaFP = SigmaFP;
GrA->A613[ix].YN = YN;
GrA->A613[ix].KSF = KSF;
GrA->A613[ix].kFP = kFP;
GrA->A613[ix].YL = YL;
GrA->A613[ix].bod = bod;
GrA->A613[ix].KHpf = KHpf;
GrA->A613[ix].Paz = Paz;
GrA->A613[ix].Pay = Pay;
ConvertMsg(ix,"ix = ");
AddLogEntry(moduleName,"SaveGearAPI613Data",msg);
AddLogEntry(moduleName,"SaveGearAPI613Data","Exit");
}
Here are the DLL log file entries:
2023.02.16 11:40:30.40 HsCalc6.54.25.HsCalc6.InitCommonGrData Entry
2023.02.16 11:40:30.40 HsCalc6.54.25.HsCalc6.InitCommonGrData ix = 0
2023.02.16 11:40:30.40 HsCalc6.54.25.HsCalc6.InitCommonGrData SaveGearAPI613Data for PINION
2023.02.16 11:40:30.40 HsCalc6.54.25.HsCalc6.InitCommonGrData Dummy=58
2023.02.16 11:40:30.40 HsCalc6.54.25.Rating6.SaveGearAPI613Data Entry
2023.02.16 11:40:30.40 HsCalc6.54.25.Rating6.SaveGearAPI613Data ix = 0
2023.02.16 11:40:30.42 HsCalc6.54.25.Rating6.SaveGearAPI613Data Saving PINION data...
2023.02.16 11:40:30.42 HsCalc6.54.25.Rating6.SaveGearAPI613Data ix = 0
2023.02.16 11:40:30.42 HsCalc6.54.25.Rating6.SaveGearAPI613Data Exit
2023.02.16 11:40:30.42 HsCalc6.54.25.HsCalc6.InitCommonGrData ix = 1
2023.02.16 11:40:30.42 HsCalc6.54.25.HsCalc6.InitCommonGrData SaveGearAPI613Data for GEAR
2023.02.16 11:40:30.42 HsCalc6.54.25.HsCalc6.InitCommonGrData Dummy=58
2023.02.16 11:40:30.42 HsCalc6.54.25.Rating6.SaveGearAPI613Data Entry
2023.02.16 11:40:30.42 HsCalc6.54.25.Rating6.SaveGearAPI613Data ix = 0
2023.02.16 11:40:30.43 HsCalc6.54.25.Rating6.SaveGearAPI613Data Saving PINION data...
2023.02.16 11:40:30.43 HsCalc6.54.25.Rating6.SaveGearAPI613Data ix = 0
As the log shows, the ix var is passed from InitCommonGrData with a value of (ix = 1), however, when SaveGearAPI613Data receives the parameter the values returns to (ix = 0). Perhaps I've been staring at this code too long and went blind in the process but I would greatly appreciate it if someone could offer some insight as to why this is happening.
I started with inline code that was refactored into the procedures outlined above. My last attempt at changing the refactored code was to add a dummy int parm to see if that made any difference when called.
The documentation seems to agree that the general limitation with parameter passing is set at 127 parms, so I don't think its the large number of parms being passed. I doubt that this is the usual question of parameter passing found on stackoverflow - so please no basic answers - unless i'm doing something stupid.
My expectation is that the application and compiler would function as advertised. Essentially, pass by value would work. Perhaps I need a different compiler setting or need to rearrange the code into the same module because of some flaw with calling external functions.

Thanks go to John Bollinger et al. The answer lies in the need to have the compiler see what is in common between the two C source files. In this case I added a new Common.h containing the two functions: declaration and prototype:
#include "Common.h"
void InitCommonGrData();
extern void SaveGearAPI613Data(double n1 , double b , double dw1, int ZE , double ZI , double ZN, double Kv , double KH , double kHP,
double CSF, double SigmaHP, double Pd , double YJ , double SigmaFP, double YN, double KSF, double kFP, int YL ,
double bod, double KHpf , double Paz, double Pay, int ix , int dummy);

Related

Solving code-forces "1A Theatre Square" in C

novice programmer here trying to get better at C, so i began doing code problems on a website called codeforces. However i seem to be stuck, i have written code that appears to work in practice but the website does not accept it as right.
the problem :
Theatre Square in the capital city of Berland has a rectangular shape with the size n × m meters. On the occasion of the city's anniversary, a decision was taken to pave the Square with square granite flagstones. Each flagstone is of the size a × a. What is the least number of flagstones needed to pave the Square? It's allowed to cover the surface larger than the Theatre Square, but the Square has to be covered. It's not allowed to break the flagstones. The sides of flagstones should be parallel to the sides of the Square.1
Source :
https://codeforces.com/problemset/problem/1/A
I did have a hard time completely understanding the math behind the problem and used this source's answer from a user named "Joshua Pan" to better understand the problem
Source :
https://www.quora.com/How-do-I-solve-the-problem-Theatre-Square-on-Codeforces
This is my code :
#include<stdio.h>
#include<math.h>
int main(void)
{
double n,m,a;
scanf("%lf %lf %lf", &n,&m,&a);
printf("%1.lf\n", ceil(n/a)*ceil(m/a));
return 0;
}
I compiled it using "gcc TheatreSquare.c -lm"
When given the sample input 6,6,4 my code produces the correct output 4, however the website does not accept this code as correct, i could be wrong but maybe im using format specifiers incorrectly?
Thanks in advance.
Typical double (IEEE754 64-bit floating point) doesn't have enough accuracy for the problem.
For example, for input
999999999 999999999 1
Your program may give output
999999998000000000
While the actual answer is
999999998000000001
To avoid this, you shouldn't use floating point data type.
You can add #include <inttypes.h> and use 64-bit integer type int64_t for this calculation.
"%" SCNd64 is for reading and "%" PRId64 is for writing int64_t.
cell(n/a) on integers can be done by (n + a - 1) / a.
You can solve this using integers.
#include <stdio.h>
int main()
{
unsigned long n, m, a = 1;
unsigned long na, ma, res = 0;
scanf("%lu %lu %lu", &n, &m, &a);
na = n/a;
if (n%a != 0)
na++;
ma = m/a;
if (m%a != 0)
ma++;
res = na * ma;
printf("%lu", res);
return 0;
}
This code will fail in the Codeforce platform, on the test 9 (see below). But if you compile it and run it locally with the same inputs, the result is correct.
> Test: #9, time: 15 ms., memory: 3608 KB, exit code: 0, checker exit code: 1, verdict: WRONG_ANSWER
> Input 1000000000 1000000000 1
> Output 2808348672 Answer 1000000000000000000
> Checker Log wrong answer 1st numbers differ - expected: '1000000000000000000', found: '2808348672'
EDIT:
The problem described above is due to the fact that I'm running a 64-bit machine and the online compiler is probably using 32-bit. The unsigned long variables overflow.
The following code will pass all the tests.
#include <stdio.h>
int main()
{
unsigned long long n, m, a = 1;
unsigned long long na, ma, res = 0;
scanf("%llu %llu %llu", &n, &m, &a);
na = n/a;
if (n%a != 0)
na++;
ma = m/a;
if (m%a != 0)
ma++;
res = na * ma;
printf("%llu", res);
return 0;
}
Use the code below it will pass all the test cases we need to use long long for all variable declaration to get output.
#include <stdio.h>
#include <math.h>
int main(){
long long n,m,a,l,b;
scanf("%lld%lld%lld",&n,&m,&a);
l= n/a;
if(n%a != 0)
l++;
b= m/a;
if(m%a != 0)
b++;
printf("%lld",l*b);
return 0;
}
Theatre Square in the capital city of Berland has a rectangular shape with the size n × m meters. On the occasion of the city's anniversary, a decision was taken to pave the Square with square granite flagstones. Each flagstone is of the size a × a.
import java.util.Scanner;
public class theatre_square {
public static void main(String[] args) {
long a,b,c;
Scanner s = new Scanner(System.in);
a = s.nextLong();
b = s.nextLong();
c = s.nextLong();
long result = 0;
if(a>=c){
if(a%c==0)
result = a/c;
else
result = a/c + 1; // some part is left
}else{ // area of rectangle < area of square then 1 square is required
result = 1;
}
if(b>=c){
if(b%c==0)
result *= b/c;
else
result *= b/c + 1;
}
System.out.println(result);
}
}
case 1 . 2 2 3 => 1
length = 2 so 2 < 3 then only 1 square required <br>
breadth = 2 so 2 < 3 then covered in previous square so output 1
intial view
0 0
0 0
after adding 1 square ( r= remaining or left)
1 1 r
1 1 r
r r r
case 2 . 6 6 4 => 4
length = 2 so 6 > 4 then only 2 square required <br>
breadth = 2 so 6 > 4 then 2 square required
intial view
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
after adding 4 square ( r= remaining or left)
1 1 1 1 2 2 r r
1 1 1 1 2 2 r r
1 1 1 1 2 2 r r
1 1 1 1 2 2 r r
3 3 3 3 4 4 r r
3 3 3 3 4 4 r r
r r r r r r r r
r r r r r r r r
You can try the following:
import math
x,y,z=list(map(float, input().split()))
print(math.ceil(x/z)*math.ceil(y/z))
Here is the code for the above problem in CPP. We need a long long variable to store the value as we may have a very large value.
GUIDANCE ABOUT THE QUESTION:
As we are given the hint of edges so we have to cover them nicely. For a rectangle, we know that we have a length and height which is shown as n * m and the square is of a*a so we will try to cover the length first and decide its squares first
for that, we divide it by k, and then if any remainder exists we will add one more and the same for height.
I hope it will help you
HERE IS THE CODE
#include<iostream>
using namespace std;
int main()
{
long long n,m,k,l=0,o=0;
cin>>n>>m>>k;
l=n/k;
if(n%k!=0)
{
l++;
}
o=m/k;
if(m%k!=0)
{
o++;
}
cout<<l*o;
}

OpenCL/C pow(x,0.5) != sqrt(x)

I guess I am in some really strange border case, maybe with double precision issues and I want to know, whats going on.
Inside an OpenCL Kernel I use:
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__private int k = 2; // I need k to be an int, because I want to use as a counter
__private double s = 18;
__private double a = 1;
a = a/(double)k; // just to show, that I make in-place typecasting of k
a = k+1;
k = (int)a; //to show that I store k in a double buffer in an intermediate-step
if ((k-1)==2)
{
// k = 3;
s = pow(s/(double)(k-1),0.5);
}
This leads me to s = 2.999[...]6
However, if I uncomment the k=3 line, I get the (in my eyes) correct result s = 3. Why is that?
As a side information: The same behaviour doesn't happen when I do
s = sqrt(s/(double)(k-1))
Below follows the full, minimal Kernel and Host code for pyopencl
Kernel (Minima.cl):
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
__kernel void init_z(__global double * buffer)
{
__private int x = get_global_id(0);
__private int y = get_global_id(1);
//w,h
__private int w_y = get_global_size(1);
__private int address = x*w_y+y;
//h,w
__private double init = 3.0;
buffer[address]=init;
}
__kernel void root(__global double * buffer)
{
__private int x = get_global_id(0);
__private int y = get_global_id(1);
//w,h
__private int w_y = get_global_size(1);
__private int address = x*w_y+y;
//h,w
__private double value = 18;
__private int k;
__private double out;
k = (int) buffer[address];
//k = 3; If this line is uncommented, the result will be exact.
out = pow(value/(double)(k-1), 0.5);
buffer[address] = out;
}
Host:
import pyopencl as cl
import numpy as np
platform = cl.get_platforms()[0]
devs = platform.get_devices()
device1 = devs[1]
h_buffer = np.empty((10,10)).astype(np.float64)
mf = cl.mem_flags
ctx = cl.Context([device1])
Queue1 = cl.CommandQueue(ctx,properties=cl.command_queue_properties.PROFILING_ENABLE)
Queue2 = cl.CommandQueue(ctx,properties=cl.command_queue_properties.PROFILING_ENABLE)
mf = cl.mem_flags
m_dic = {0:mf.READ_ONLY,1:mf.WRITE_ONLY,2:mf.READ_WRITE}
fi = open('Minimal.cl', 'r')
fstr = "".join(fi.readlines())
prg = cl.Program(ctx, fstr).build()
knl = prg.init_z
knl.set_scalar_arg_dtypes([None,])
knl_root = prg.root
knl_root.set_scalar_arg_dtypes([None,])
def f():
d_buffer = cl.Buffer(ctx,m_dic[2], int(10 * 10 * 8))
knl.set_args(d_buffer)
knl_root.set_args(d_buffer)
a = cl.enqueue_nd_range_kernel(Queue2,knl,(10,10),None)
b = cl.enqueue_nd_range_kernel(Queue2,knl_root,(10,10),None, wait_for = [a,])
cl.enqueue_copy(Queue1,h_buffer,d_buffer,wait_for=[b,])
return h_buffer
a = f()
a[0,0] # Getting the result on the host.
Edit: Because of some more unclarities I update this question one more time. I understand, that the value of pow and sqrt doesn't have to be the same for the same input. My question is, why pow shows different output for the SAME input, depending on where I get it from.
The binaries are on pastebin:
k_explicit and k_read
printf("a%\n", out) leads to 0x1.8p+1 with the k=3 line and to 0x1.7ffffffffffffp+1 when it's commented out.
Floating point calculations are not exact. So using one algorithm (sqrt) and a different one (pow()) with the same inputs cannot be expected to give bitwise-identical results. If both results are within ±epsilon of the mathematically true value, then both implementations are acceptable.
Typically, pow() is implemented in terms of ln() and exp() (with a multiplication in between), whereas sqrt() can use a much faster implementation (which probably involves halving the mantissa as a first step).
So, after lots of discussion it doesn't seem to be a problem with my code. The behaviour seems to be hardware-dependent and so far only reproducable on Nvidia Hardware. I'm still interested in the "why" and "how" that happens but in this case the question is answered.

Struct and file handling

The program I am making must store the values in the text file on their respective variables. The problem seems to arise in the inner loop. I have the respective structs already defined. The program runs properly for the outer loop but when it proceeds in the inner loop, the file pointer does not read the proper values from the text file and outputs "0.0" and does not proceed with the processes from the outer loop altogether.
my input file looks something like this:
GENERAL
1 4
PANELS
1 2.1 3.1 4.1 5.1 6.1 7.1 1
2 2.2 3.2 4.2 5.2 6.2 7.2 2
1 2.21 3.21 4.21 5.21
2 2.22 3.22 4.22 5.22
3 2.3 3.3 4.3 5.3 6.3 7.3 0
4 2.4 3.4 4.4 5.4 6.4 7.4 4
1 2.41 3.41 4.41 5.41
2 2.42 3.42 4.42 5.42
3 2.43 3.43 4.43 5.43
4 2.44 3.44 4.44 5.44
MATERIAL
1 1000.0 2000.0 3000.0 4000.0
2 1010.0 2020.0 3030.0
3 1010.1 2020.2
CHB
1 10 20 30 2
2 11 22 33 1
these are just placeholders to see if they are stored. single digits are integers while floats have decimal points.
here is the code
typedef struct _open
{
int id;
double length;
double height;
double origX;
double origY;
int frames;
double thickness;
double E;
double v;
}CHBOpening;
typedef struct _panels
{
int id;
double length;
double height;
double origX;
double origY;
double origZ;
double angle;
int nOpenings;
int nReinforcement;
double *xReinf;
double sx;
double xReinf0;
CHBUnit *chb;
CHBOpening *openings[];
}CHBPanel;
typedef struct _chb
{
int nStories;
int nModes;
int nIter;
int nPanels;
CHBPanel *panels[];
}CHBStructure;
int ReadPanelBlock (FILE *fp, CHBStructure *S)
{
int i,j;
S->panels = malloc(S->nPanels*sizeof(CHBStructure));
for (i=0; i< S->nPanels; i++)
{
fscanf(fp,"%d",&S->panels[i].id);
fscanf(fp,"%lf",&S->panels[i].length);
fscanf(fp,"%lf",&S->panels[i].height);
fscanf(fp,"%lf",&S->panels[i].angle);
fscanf(fp,"%lf",&S->panels[i].origX);
fscanf(fp,"%lf",&S->panels[i].origY);
fscanf(fp,"%lf",&S->panels[i].origZ);
fscanf(fp,"%d",&S->panels[i].nOpenings);
if (S->panels[i].nOpenings > 0)
{
S->panels[i].openings = malloc(sizeof(CHBOpening)*S->panels[i].nOpenings);
for (j=0; j<S->panels[i].nOpenings;j++)
{
fscanf(fp,"%d",&S->panels[i].openings[j].id);
fscanf(fp,"%lf",&S->panels[i].openings[j].length);
fscanf(fp,"%lf",&S->panels[i].openings[j].height);
fscanf(fp,"%lf",&S->panels[i].openings[j].origX);
fscanf(fp,"%lf",&S->panels[i].openings[j].origY);
}
}
}
return 1;
}
When you allocate pannels you do
S->panels = malloc(S->nPanels*sizeof(CHBStructure));
The problem here is that you use sizeof(CHBStructure) instead of sizeof(CHBPanel). The problem with this is that sizeof(CHBStructure) < sizeof(CHBPanel), so you don't allocate enough memory for the data you read.
That will lead to writing out of bounds, and undefined behavior.
This is in addition to the "typo" in the input file, which will lead you to enter the inner loop when there's nothing to read.

Compiling gives different results than windows compiler

I tried to compile and run some old C programs that I developed years back on windows with codeblocks.
I get no error from gcc and program executes correctly. Only in some cases (some initial conditions), I do not get the same numerical results as before! I did not change anything in my program (except sed the ^M characters).
I first thought it was because of the two scanf functions. But no. I removed them and get the same erroneous results.
Did anyone encounter that kind of strange behavior before when using a Windows C code to linux?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "differentialeqsolve.h"
#define TINY 1.0e-30
/*----------------------------------------------------------------------------------------------*/
/*main*/
/*----------------------------------------------------------------------------------------------*/
int main(void){
/*miscellaneous variables*/
int i,k,dummy;
int N=4; /*nb equa diff +1 (we don't want to use f[0])*/
/*output files*/
char namefile[20]={0}; /*file for couplings*/
FILE * file[N];
/*Runge Kutta variables*/
double accuracy=1e-7; /*minimal precision required for values of f obtained by rk*/
double h=1.0e-7; /*initial step for RG (for the first iteration)*/
double htry,hdid,hnext; /*initial/effective/final step for rk5adapt*/
double t=0.; /*RG time*/
double limite=1.0e12; /*cutoff limit for the strong coupling*/
double U,J; /*lattice parameters for initial conditions*/
int NN; /*number of spin components*/
double thetamin,thetamax,dtheta;
double theta;
double R=0.1;
int n=100; /*number of points in the calculation around the ring*/
double f[N];
double df[N];
double fscal[N];
double g[N]; /*renormalized (by f1) couplings*/
/*opening output files*/
for (k = 1 ; k < N ; k++ )
{sprintf(namefile,"g%d.dat",k);
file[k]=fopen(namefile, "w");}
/*initialization of couplings f[]*/
NN=3;
thetamin = -0.1;
thetamax = 0.1;
dtheta=(thetamax-thetamin)/((float) n);
printf("dtheta=%.10lf\n",dtheta);
for(i=0;i<=n;i++){
theta=thetamin+i*dtheta;
U=R*cos(theta);
J=R*sin(theta);
/*initialization of table df[]*/
for(k=1;k<N;k++) df[k]=0;
f[1]=-2*NN*U-3*NN*J;
f[2]=-2*NN*U+NN*J+2*NN*NN*J;
f[3]=-2*NN*U+NN*J;
t=0.; /*initialization of RG time*/
/*initialization of RG time step for rk5adapt*/
htry=h;
/*calculation of the scaling to calculate precision*/
for(k=1;k<N;k++)
fscal[k]=fabs(f[k])+fabs(df[k]*htry)+TINY;
/* ********************************************************/
/*iteration of RG until at least one of the couplings reaches the cutoff "limite"*/
/* ********************************************************/
for(;;){
/*calculation of f(t+h) with rk5adapt*/
rk5adapt(f,df,N,NN,&t,htry,accuracy,fscal,&hdid,&hnext,dfunctions);
/*new time is readily set by rk5adapt*/
/*new step (set as hnext by rk5adapt)*/
htry=hnext;
/*new scaling fscal*/
for(k=1;k<N;k++)
fscal[k]=fabs(f[k])+fabs(df[k]*htry)+TINY;
/*Stop RG iteration when at least one of the couplings reaches the cutoff limit*/
for(k=1;k<N;k++)
{if(fabs(f[k])>=limite) {goto RGstop;}}
}
RGstop : if(f[1]>0) for(k=1;k<N;k++)
{
g[k]=f[k]/f[1];
fprintf(file[k],"%lf %lf\n",theta,g[k]);
}
else printf("%lf, g[1]<0\n",theta);
/*end theta*/
}
for ( k = 1 ; k < N ; k++ )
{
fclose(file[k]);
}
return 0;
}
Ok, I solved the problem by setting the TINY parameter (see Runge Kutta in Numerical Recipes) to 1e-25. Before it was set at 1e-30.
Apparently, my compiler does not treat float and float operations the same way my old compiler did.
Following chux remarks, I checked the value of FLT_EVAL_METHOD which was 0. Setting it to 2 changed a little bit the results of my differential equations but it's only when I set TINY to a different value that I finally got the expected results.

Getting p-value for linear regression in C gsl_fit_linear() function from GSL library

I'm trying to reporduce some code from R in C, so I'm trying to fit a linear regression using the gsl_fit_linear() function.
In R I'd use the lm() function, which returns a p-value for the fit using this code:
lmAvgs<- lm( c(1.23, 11.432, 14.653, 21.6534) ~ c(1970, 1980, 1990, 2000) )
summary(lmAvgs)
I've no idea though how to go from the C output to a p-value, my code looks something like this so far:
int main(void)
{
int i, n = 4;
double x[4] = { 1970, 1980, 1990, 2000 };
double y[4] = {1.23, 11.432, 14.653, 21.6534};
double c0, c1, cov00, cov01, cov11, sumsq;
gsl_fit_linear (x, 1, y, 1, n, &c0, &c1, &cov00, &cov01, &cov11, &sumsq);
}
This seems to correctly calculate slope and intercept but I don't know how to get a p-value. I'm novice at stats and C!
Everything is on : http://en.wikipedia.org/wiki/Ordinary_least_squares. but here is a piece of code which display an output similar to summary(lmAvgs) in R. To run this, you need the GSL Library :
int n = 4;
double x[4] = { 1970, 1980, 1990, 2000};
double y[4] = {1.23, 11.432, 14.653, 21.6534};
double c0, c1, cov00, cov01, cov11, sumsq;
gsl_fit_linear (x, 1, y, 1, n, &c0, &c1, &cov00, &cov01, &cov11, &sumsq);
cout<<"Coefficients\tEstimate\tStd. Error\tt value\tPr(>|t|)"<<endl;
double stdev0=sqrt(cov00);
double t0=c0/stdev0;
double pv0=t0<0?2*(1-gsl_cdf_tdist_P(-t0,n-2)):2*(1-gsl_cdf_tdist_P(t0,n-2));//This is the p-value of the constant term
cout<<"Intercept\t"<<c0<<"\t"<<stdev0<<"\t"<<t0<<"\t"<<pv0<<endl;
double stdev1=sqrt(cov11);
double t1=c1/stdev1;
double pv1=t1<0?2*(1-gsl_cdf_tdist_P(-t1,n-2)):2*(1-gsl_cdf_tdist_P(t1,n-2));//This is the p-value of the linear term
cout<<"x\t"<<c1<<"\t"<<stdev1<<"\t"<<t1<<"\t"<<pv1<<endl;
double dl=n-2;//degrees of liberty
double ym=0.25*(y[0]+y[1]+y[2]+y[3]); //Average of vector y
double sct=pow(y[0]-ym,2)+pow(y[1]-ym,2)+pow(y[2]-ym,2)+pow(y[3]-ym,2); // sct = sum of total squares
double R2=1-sumsq/sct;
cout<<"Multiple R-squared: "<<R2<<", Adjusted R-squared: "<<1-double(n-1)/dl*(1-R2)<<endl;
double F=R2*dl/(1-R2);
double p_value=1-gsl_cdf_fdist_P(F,1,dl);
cout<<"F-statistic: "<<F<<" on 1 and "<<n-2<<" DF, p-value: "<<p_value<<endl;
Which gives :
Coefficients Estimate Std. Error t value Pr(>|t|)
Intercept -1267.91 181.409 -6.98922 0.0198633
x 0.644912 0.0913886 7.05681 0.0194956
Multiple R-squared: 0.961389, Adjusted R-squared: 0.942083
F-statistic: 49.7986 on 1 and 2 DF, p-value: 0.0194956
R gives :
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.268e+03 1.814e+02 -6.989 0.0199 *
c(1970, 1980, 1990, 2000) 6.449e-01 9.139e-02 7.057 0.0195 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.044 on 2 degrees of freedom
Multiple R-squared: 0.9614, Adjusted R-squared: 0.9421
F-statistic: 49.8 on 1 and 2 DF, p-value: 0.01950

Resources