#include <stdio.h>
#include <math.h>
#include <float.h>

static double numdiff_central(double (*f)(double), double x, double h) {
    return (f(x + h) - f(x - h)) / (2 * h);
}


static double numdiff_right(double (*f)(double), double x, double h) {
    return (f(x + h) - f(x)) / h;
}


#define NUMDIFF(f, x) { \
    volatile double h = sqrt(DBL_EPSILON) * (x); \
    \
    printf("right-hand diff. of " #f "(x) for x = " #x ": %lf\n", \
           numdiff_right(f, x, h)); \
    \
    printf("central diff.    of " #f "(x) for x = " #x ": %lf\n", \
           numdiff_central(f, x, h)); \
    \
    printf("calculated h = √e * (" #x "): %lf\n\n", h); \
}


int main(void)
{
    NUMDIFF(sin, M_PI / 3.0);
    NUMDIFF(sin, 100 * M_PI + M_PI / 3.0);
    NUMDIFF(sin, 10e12 * M_PI + M_PI / 3.0);

    return 0;
}
