0

I have this function. I'm kinda green in C and I don't know how to call this function to get a result:

float dbrent(float ax, float bx, float cx, float (*f)(float),float (*df)(float), float tol, float* xmin)
{
    int iter, ok1, ok2;
    float a, b, d, d1, d2, du, dv, dw, dx, e = 0.0;
    float fu, fv, fw, fx, olde, tol1, tol2, u, u1, u2, v, w, x, xm;
    a = (ax < cx ? ax : cx);
    b = (ax > cx ? ax : cx);
    x = w = v = bx;
    fw = fv = fx = (*f)(x);
    dw = dv = dx = (*df)(x);

    for (iter = 1; iter <= ITMAX; iter++)
    {
        xm = 0.5 * (a + b);
        tol1 = tol * fabs(x) + ZEPS;
        tol2 = 2.0 * tol1;
        if (fabs(x - xm) <= (tol2 - 0.5 * (b - a))) {
            *xmin = x;
            return fx;
        }
        if (fabs(e) > tol1) {
            d1 = 2.0 * (b - a);
            d2 = d1;
            if (dw != dx) d1 = (w - x) * dx / (dx - dw);
            if (dv != dx) d2 = (v - x) * dx / (dx - dv);
            u1 = x + d1;
            u2 = x + d2;
            ok1 = (a - u1) * (u1 - b) > 0.0 && dx * d1 <= 0.0;
            ok2 = (a - u2) * (u2 - b) > 0.0 && dx * d2 <= 0.0;
            olde = e;
            e = d;
            if (ok1 || ok2) {
                if (ok1 && ok2)
                    d = (fabs(d1) < fabs(d2) ? d1 : d2);
                else if (ok1)
                    d = d1;
                else
                    d = d2;
                if (fabs(d) <= fabs(0.5 * olde)) {
                    u = x + d;
                    if (u - a < tol2 || b - u < tol2)
                        d = SIGN(tol1, xm - x);
                }
                else {
                    d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
                }
            }
            else {
                d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
            }
        }
        else {
            d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
        }
        if (fabs(d) >= tol1) {
            u = x + d;
            fu = (*f)(u);
        }
        else {
            u = x + SIGN(tol1, d);
            fu = (*f)(u);
            if (fu > fx) {
                *xmin = x;
                return fx;
            }
        }
        du = (*df)(u);
        if (fu <= fx) {
            if (u >= x) a = x; else b = x;
            MOV3(v, fv, dv, w, fw, dw)
                MOV3(w, fw, dw, x, fx, dx)
                MOV3(x, fx, dx, u, fu, du)
        }
        else {
            if (u < x) a = u; else b = u;
            if (fu <= fw || w == x) {
                MOV3(v, fv, dv, w, fw, dw)
                    MOV3(w, fw, dw, u, fu, du)
            }
            else if (fu < fv || v == x || v == w) {
                MOV3(v, fv, dv, u, fu, du)
            }
        }
    }
    cout<<"Too many iterations in routine dbrent";
    return 0.0;
}

This code is from Numerical Recipes Chapter 10.3. I need to call this function and get the result but I don't know how to call it, especially when there is a syntax like float (*)(float).

Thanks in advance.

2 Answers2

2

We can call dbrent in several ways, the below shown is one of the ways.

Your function prototype

float dbrent ( float ax, float bx, float cx, 
               float (*f)(float),
               float (*df)(float), 
               float tol, float* xmin
             )

what you need is a func_f (you can use any name for function) that takes a float value as an argument and returns a float value as shown below.

float func_f(float num)
{
    /* code */
}

you need one more function with same type as mentioned above

float func_df(float num)
{
    /* code */
}

Following is the setup you need to make before calling dbrent

some_funtion()
{
    // setup to call dbrent
    // guess you know you need some values in it.
    float ax, bx,  cx, tol, xmin;
    float (*f)(float);
    float (*df)(float);
    f = func_f;
    df = func_df;

     //one way of calling dbrent
    dbrent(ax, bx,  cx, f, df,tol, xmin);

    //you can even directly call using the function names instead of using pointers
    dbrent(ax, bx, cx, func_f, func_df, tol, xmin);
}

NOTE: variables have not been initialized for simplicity, make sure you pass valid variables when calling the function.

IrAM
  • 1,720
  • 5
  • 18
  • Why not simply `dbrent(ax, bx, cx, func1, func_df, tol, xmin);` and drop `float (*f)(float); float (*df)(float);` alltogether? – Jabberwocky Jan 06 '21 at 10:48
  • yes @Jabberwocky, i was editing the same , and that is why I mentioned at beginning _several ways_ :), thanks anyway – IrAM Jan 06 '21 at 10:53
  • Nevertheless having these intermediate functions pointers `f` and `df` is totally pointless. Is just make the code harder to read. – Jabberwocky Jan 06 '21 at 10:56
  • I was just letting him know different ways, agree declaring `f` and `df` are actually not needed, but no harm done. – IrAM Jan 06 '21 at 11:01
2

Well, let's suppose you have the following functions:

float df_(float yourFloat) {
  ...
  return yourFloat;
}

and

float f_(float yourFloat) {
  ...
  return yourFloat;
}

Then you could call your function as follows:

float t =  dbrent(ax, bx, cx, &f_, &df_, tol, &xmin);

Where &xmin hands over the address of some float variable xmin.

So, in essence, you supply the address of your functions f_ and df_ and your float variable xmin.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
muzzletov
  • 640
  • 4
  • 13