#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <string.h>

#define is_close_abs(a, expected, abs) \
    assert(fabs((a) - (expected)) <= (abs))

#define is_close_rel(a, expected, rel) \
    do { \
        assert(isfinite(a)); \
        if (((fabs((a) - (expected))) / fabs(expected)) > (rel)) { \
            printf("%g - %g = (%g %g%%)\n", a, expected, fabs(a - expected), \
                   100*fabs((a - expected) / expected)); \
            assert(((fabs((a) - (expected))) / fabs(expected)) <= (rel)); \
        } \
    } \
    while (0)

int g2efit(float *val, float * wght, int nx, int ny, float *ap,
           float *cv, double *pchi);

void test_gauss2d(void)
{
    int i;
    int nx = 64, ny = 63;
    
    FILE * f = fopen("data6463.dat", "rb");
    float data[nx * ny]; /* fortran order */
    float sig[nx * ny]; /* fortran order */
    fread(&data, 4, nx * ny, f);
    fclose(f);
    float a[6] = {
        0.00234707491,
        37.2615662, 9.13963032,
        31.9156647, 7.84213734,
        0.568262696};
    float cv[6];
    double chi;
    for (i = 0; i < nx * ny; i++) {
        sig[i] = 1.;
    }

    g2efit(data, sig, nx, ny, a, cv, &chi);
    
    double rel = 0.015;
    is_close_rel(a[0], 0.00241090008, rel);
    is_close_rel(a[1], 37.0322304, rel);
    is_close_rel(a[2], 25.3530064, rel);
    is_close_rel(a[3], 31.8684464, rel);
    is_close_rel(a[4], 7.40274811, rel);
    is_close_rel(a[5], 0.580113709, rel);

    is_close_rel(cv[0], 0.0625443384, rel);
    is_close_rel(cv[1], 631.03949, rel);
    is_close_rel(cv[2], 939.648193, rel);
    is_close_rel(cv[3], 424.865265, rel);
    is_close_rel(cv[4], 185.996353, rel);
    is_close_rel(cv[5], 13.0091639, rel);
}

int main(int argc, const char *argv[])
{
    test_gauss2d();
    return 0;
}
