5

Hi I have the following function called zeroin I'd like to compile and link in with a Cpp file but I can't get past the first step of compiling the c file. The function is called zeroin.c I obtained from here. I have put the file in it's own directory, cd'd to it, and since it uses math.h I have used gcc with the -lm flag to make sure the library is linked in.

gcc -Wall -O zeroin.c -o zeroin -lm 

However I get the following errors:

zeroin.C:50:15: error: 'ax' was not declared in this scope zeroin.C:50:18: error: 'bx' was not declared in this scope zeroin.C:50:21: error: 'f' was not declared in this scope zeroin.C:50:23: error: 'tol' was not declared in this scope zeroin.C:50:26: error: expression list treated as compound expression in initialiser [-fpermissive] zeroin.C:51:1: error: expected ',' or ';' before 'double' zeroin.C:55:1: error: expected unqualified-id before '{' token 

I've included the code for the C code function below - I don't really know C very well and am only trying to compile it so as to use it to find roots for functions in a C++ file I have. How can I solve these errors?

Thanks, Ben.

#include "math.h" double zeroin(ax,bx,f,tol) /* An estimate to the root */ double ax; /* Left border | of the range */ double bx; /* Right border| the root is seeked*/ double (*f)(double x); /* Function under investigation */ double tol; /* Acceptable tolerance */ { double a,b,c; /* Abscissae, descr. see above */ double fa; /* f(a) */ double fb; /* f(b) */ double fc; /* f(c) */ a = ax; b = bx; fa = (*f)(a); fb = (*f)(b); c = a; fc = fa; for(;;) /* Main iteration loop */ { double prev_step = b-a; /* Distance from the last but one*/ /* to the last approximation */ double tol_act; /* Actual tolerance */ double p; /* Interpolation step is calcu- */ double q; /* lated in the form p/q; divi- */ /* sion operations is delayed */ /* until the last moment */ double new_step; /* Step at this iteration */ if( fabs(fc) < fabs(fb) ) { /* Swap data for b to be the */ a = b; b = c; c = a; /* best approximation */ fa=fb; fb=fc; fc=fa; } tol_act = 2*EPSILON*fabs(b) + tol/2; new_step = (c-b)/2; if( fabs(new_step) <= tol_act || fb == (double)0 ) return b; /* Acceptable approx. is found */ /* Decide if the interpolation can be tried */ if( fabs(prev_step) >= tol_act /* If prev_step was large enough*/ && fabs(fa) > fabs(fb) ) /* and was in true direction, */ { /* Interpolatiom may be tried */ register double t1,cb,t2; cb = c-b; if( a==c ) /* If we have only two distinct */ { /* points linear interpolation */ t1 = fb/fa; /* can only be applied */ p = cb*t1; q = 1.0 - t1; } else /* Quadric inverse interpolation*/ { q = fa/fc; t1 = fb/fc; t2 = fb/fa; p = t2 * ( cb*q*(q-t1) - (b-a)*(t1-1.0) ); q = (q-1.0) * (t1-1.0) * (t2-1.0); } if( p>(double)0 ) /* p was calculated with the op-*/ q = -q; /* posite sign; make p positive */ else /* and assign possible minus to */ p = -p; /* q */ if( p < (0.75*cb*q-fabs(tol_act*q)/2) /* If b+p/q falls in [b,c]*/ && p < fabs(prev_step*q/2) ) /* and isn't too large */ new_step = p/q; /* it is accepted */ /* If p/q is too large then the */ /* bissection procedure can */ /* reduce [b,c] range to more */ /* extent */ } if( fabs(new_step) < tol_act ) /* Adjust the step to be not less*/ if( new_step > (double)0 ) /* than tolerance */ new_step = tol_act; else new_step = -tol_act; a = b; fa = fb; /* Save the previous approx. */ b += new_step; fb = (*f)(b); /* Do step to a new approxim. */ if( (fb > 0 && fc > 0) || (fb < 0 && fc < 0) ) { /* Adjust c for it to have a sign*/ c = a; fc = fa; /* opposite to that of b */ } } } 

--EDIT--

Thank you for everyone's suggestions, I've changed the format to ANSI format and changed EPSILON to DBL_EPSILON and also altered #include"math.h" to say #include - the updated function (is included below). However if I try to compile this time:

$gcc -Wall zeroin.c -o zeroin -lm zeroin.c: In function 'zeroin': zeroin.c:78:17: error: 'DBL_EPSILON' undeclared (first use in this function) zeroin.c:78:17: note: each undeclared identifier is reported only once for each function it appears in zeroin.c:116:7: warning: suggest explicit braces to avoid ambiguous 'else' [-Wparentheses] 

Am is there maybe another library I need for DBL_EPSILON if it's saying that it's not defined?

Thanks, Ben.

#include <math.h> double zeroin(double ax, double bx, double(*f)(double x), double tol) /* An estimate to the root */ { double a,b,c; /* Abscissae, descr. see above */ double fa; /* f(a) */ double fb; /* f(b) */ double fc; /* f(c) */ a = ax; b = bx; fa = (*f)(a); fb = (*f)(b); c = a; fc = fa; for(;;) /* Main iteration loop */ { double prev_step = b-a; /* Distance from the last but one*/ /* to the last approximation */ double tol_act; /* Actual tolerance */ double p; /* Interpolation step is calcu- */ double q; /* lated in the form p/q; divi- */ /* sion operations is delayed */ /* until the last moment */ double new_step; /* Step at this iteration */ if( fabs(fc) < fabs(fb) ) { /* Swap data for b to be the */ a = b; b = c; c = a; /* best approximation */ fa=fb; fb=fc; fc=fa; } tol_act = 2*DBL_EPSILON*fabs(b) + tol/2; new_step = (c-b)/2; if( fabs(new_step) <= tol_act || fb == (double)0 ) { return b; /* Acceptable approx. is found */ } /* Decide if the interpolation can be tried */ if( fabs(prev_step) >= tol_act /* If prev_step was large enough*/ && fabs(fa) > fabs(fb) ) /* and was in true direction, */ { /* Interpolatiom may be tried */ register double t1,cb,t2; cb = c-b; if( a==c ) /* If we have only two distinct */ { /* points linear interpolation */ t1 = fb/fa; /* can only be applied */ p = cb*t1; q = 1.0 - t1; } else /* Quadric inverse interpolation*/ { q = fa/fc; t1 = fb/fc; t2 = fb/fa; p = t2 * ( cb*q*(q-t1) - (b-a)*(t1-1.0) ); q = (q-1.0) * (t1-1.0) * (t2-1.0); } if( p>(double)0 ) /* p was calculated with the op-*/ q = -q; /* posite sign; make p positive */ else /* and assign possible minus to */ p = -p; /* q */ if( p < (0.75*cb*q-fabs(tol_act*q)/2) /* If b+p/q falls in [b,c]*/ && p < fabs(prev_step*q/2) ) /* and isn't too large */ new_step = p/q; /* it is accepted */ /* If p/q is too large then the */ /* bissection procedure can */ /* reduce [b,c] range to more */ /* extent */ } if( fabs(new_step) < tol_act ) /* Adjust the step to be not less*/ if( new_step > (double)0 ) /* than tolerance */ new_step = tol_act; else new_step = -tol_act; a = b; fa = fb; /* Save the previous approx. */ b += new_step; fb = (*f)(b); /* Do step to a new approxim. */ if( (fb > 0 && fc > 0) || (fb < 0 && fc < 0) ) { /* Adjust c for it to have a sign*/ c = a; fc = fa; /* opposite to that of b */ } } } 
2
  • What gives you the idea that your problem had anything to do with math.h? Commented Feb 6, 2014 at 12:04
  • For correctness, you should #include <math.h> (library header) rather than "math.h" (user-defined header) but that's not likely the cause of the problem. Commented Feb 6, 2014 at 12:11

5 Answers 5

8

This code uses the ancient pre-standard style of function signature, with the types of the parameters after the parameter list.

Change

double zeroin(ax,bx,f,tol) /* An estimate to the root */ double ax; /* Left border | of the range */ double bx; /* Right border| the root is seeked*/ double (*f)(double x); /* Function under investigation */ double tol; /* Acceptable tolerance */ { 

to:

double zeroin(double ax, double bx, double (*f)(double), double tol) { 

There's surely a way to make gcc accept the old style, but unless you're worried about merge conflicts from upstream changes, you may as well just update it :-)

Sign up to request clarification or add additional context in comments.

Comments

8

It looks like the filename has a capitalised extension, .C, which makes GCC think that it's C++ rather than C. The code is in an ancient dialect of C (known as "K&R style") which isn't compatible with C++.

Rename the file to zeroin.c, or specify the language on the command line with -x c.

Alternatively, if you need to use a compiler that doesn't understand K&R syntax, you could change the function header to use modern syntax:

double zeroin(double ax, double bx, double(*f)(double x), double tol) { // code here } 

The remaining problem is the use of EPSILON; in a modern C library, that's called DBL_EPSILON.

1 Comment

Thanks I've changed the file extension, now I'll work through the other syntax changes and see how it goes.
4

I presume this is very old C code. The syntax for declaring the zeroin function this way

double zeroin(ax,bx,f,tol) /* An estimate to the root */ double ax; /* Left border | of the range */ double bx; /* Right border| the root is seeked*/ double (*f)(double x); /* Function under investigation */ double tol; /* Acceptable tolerance */ 

is quite old and now deprecated, so your compiler doesn't understand it. Change it to this:

double zeroin(double ax, double bx, double (*f)(double x), double tol) 

Comments

1

You are using K & R style of function declaration

Try using ANSI Standard style:

double zeroin(double ax,double bx, double (*f)(double), double tol); 

Comments

0

Am is there maybe another library I need for DBL_EPSILON if it's saying that it's not defined?

Perhaps

#include <float.h> 

needed

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.