264 lines
5.4 KiB
C
264 lines
5.4 KiB
C
|
|
/*
|
|
* Author: Graeme Gill
|
|
* Date: 30/10/2005
|
|
*
|
|
* Copyright 2005 Graeme W. Gill
|
|
* Parts derived from rspl/c1.c, cv.c etc.
|
|
*
|
|
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
|
|
* see the License.txt file for licencing details.
|
|
*
|
|
* Test monocurve class.
|
|
*
|
|
*/
|
|
|
|
#undef DIAG
|
|
#undef TEST_SYM
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <math.h>
|
|
#include "copyright.h"
|
|
#include "aconfig.h"
|
|
#include "numlib.h"
|
|
#include "moncurve.h"
|
|
#include "plot.h"
|
|
#include "ui.h"
|
|
|
|
double lin(double x, double xa[], double ya[], int n);
|
|
void usage(void);
|
|
|
|
#define TRIALS 30 /* Number of random trials */
|
|
#define SKIP 0 /* Number of random trials to skip */
|
|
#undef NORMONLY /* Defined to use 0.0 - 1.0 limited curve */
|
|
|
|
#undef ORDER_STEP /* Step orders from 2 to SHAPE_ORDERS */
|
|
//#define SHAPE_ORDS 30 /* Number of order to use */
|
|
#define SHAPE_ORDS 12 /* Number of order to use */
|
|
|
|
#define ABS_MAX_PNTS 100
|
|
|
|
#define MIN_PNTS 2
|
|
#define MAX_PNTS 20
|
|
|
|
#define MIN_RES 20
|
|
#define MAX_RES 500
|
|
|
|
double xa[ABS_MAX_PNTS];
|
|
double ya[ABS_MAX_PNTS];
|
|
|
|
#define XRES 100
|
|
|
|
#define TSETS 3 /* Number of special test sets */
|
|
#define PNTS 11
|
|
#define GRES 100
|
|
int t1p[TSETS] = {
|
|
4,
|
|
11,
|
|
11
|
|
};
|
|
|
|
double t1xa[TSETS][PNTS] = {
|
|
{ 0.0, 0.2, 0.8, 1.0 },
|
|
{ 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 },
|
|
{ 0.0, 0.25, 0.30, 0.35, 0.40, 0.44, 0.48, 0.51, 0.64, 0.75, 1.0 }
|
|
};
|
|
|
|
double t1ya[TSETS][PNTS] = {
|
|
{ 0.0, 0.5, 0.6, 1.0 },
|
|
{ 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.8, 1.0, 1.0, 1.0 },
|
|
{ 0.0, 0.35, 0.4, 0.41, 0.42, 0.46, 0.5, 0.575, 0.48, 0.75, 1.0 }
|
|
};
|
|
|
|
|
|
mcvco test_points[ABS_MAX_PNTS];
|
|
|
|
double lin(double x, double xa[], double ya[], int n);
|
|
|
|
void
|
|
usage(void) {
|
|
puts("usage: monctest");
|
|
exit(1);
|
|
}
|
|
|
|
int main() {
|
|
mcv *p;
|
|
int i, n;
|
|
double x, y;
|
|
double xx[XRES];
|
|
double y1[XRES];
|
|
double y2[XRES];
|
|
int np = SHAPE_ORDS; /* Number of harmonics */
|
|
|
|
error_program = "monctest";
|
|
|
|
#ifdef NORMONLY
|
|
printf("Testing fixed offset = 0 and scale = 1.0\n");
|
|
if ((p = new_mcv_noos()) == NULL)
|
|
#else
|
|
if ((p = new_mcv()) == NULL)
|
|
#endif
|
|
error("new_mcv failed");
|
|
|
|
for (n = 0; n < TRIALS; n++) {
|
|
double lrand; /* Amount of level randomness */
|
|
int pnts;
|
|
|
|
if (n < TSETS) /* Standard versions */ {
|
|
pnts = t1p[n];
|
|
for (i = 0; i < pnts; i++) {
|
|
xa[i] = t1xa[n][i];
|
|
ya[i] = t1ya[n][i];
|
|
}
|
|
} else if (n == TSETS) { /* Exponential function aproximation */
|
|
double ex = 2.4;
|
|
pnts = MAX_PNTS;
|
|
|
|
printf("Trial %d, no points = %d, exponential %f\n",n,pnts,ex);
|
|
|
|
/* Create X values */
|
|
for (i = 0; i < pnts; i++)
|
|
xa[i] = pow(i/(pnts-1.0), 1.0);
|
|
|
|
for (i = 0; i < pnts; i++)
|
|
ya[i] = pow(xa[i], ex);
|
|
|
|
} else if (n == TSETS + 1) { /* inverse exponential function aproximation */
|
|
double ex = 1.0/2.4;
|
|
pnts = MAX_PNTS;
|
|
|
|
printf("Trial %d, no points = %d, exponential %f\n",n,pnts,ex);
|
|
|
|
/* Create X values */
|
|
for (i = 0; i < pnts; i++)
|
|
xa[i] = pow(i/(pnts-1.0), 3.0);
|
|
|
|
for (i = 0; i < pnts; i++)
|
|
ya[i] = pow(xa[i], ex);
|
|
|
|
} else { /* Random versions */
|
|
double ymax;
|
|
lrand = d_rand(0.0,0.2); /* Amount of level randomness */
|
|
lrand *= lrand;
|
|
pnts = i_rand(MIN_PNTS,MAX_PNTS);
|
|
|
|
printf("Trial %d, no points = %d, level randomness = %f\n",n,pnts,lrand);
|
|
|
|
/* Create X values */
|
|
xa[0] = 0.0;
|
|
for (i = 1; i < pnts; i++)
|
|
xa[i] = xa[i-1] + d_rand(0.5,1.0);
|
|
for (i = 0; i < pnts; i++) /* Divide out */
|
|
xa[i] = (xa[i]/xa[pnts-1]);
|
|
|
|
/* Create y values */
|
|
ya[0] = xa[0] + d_rand(-0.2, 0.7);
|
|
for (i = 1; i < pnts; i++)
|
|
ya[i] = ya[i-1] + d_rand(0.1,1.0) + d_rand(-0.1,0.4) + d_rand(-0.4,0.5);
|
|
|
|
ymax = d_rand(0.6, 10.2); /* Scale target */
|
|
for (i = 0; i < pnts; i++) {
|
|
ya[i] = ymax * (ya[i]/ya[pnts-1]);
|
|
// if (ya[i] < 0.0)
|
|
// ya[i] = 0.0;
|
|
// else if (ya[i] > 1.0)
|
|
// ya[i] = 1.0;
|
|
}
|
|
}
|
|
|
|
if (n < SKIP)
|
|
continue;
|
|
|
|
for (i = 0; i < pnts; i++) {
|
|
test_points[i].p = xa[i];
|
|
test_points[i].v = ya[i];
|
|
test_points[i].w = 1.0;
|
|
}
|
|
/* Test weighting */
|
|
test_points[pnts-1].w = 1.0;
|
|
|
|
#ifdef ORDER_STEP
|
|
for (np = 2; np <= SHAPE_ORDS; np++) {
|
|
#else /* Full number of orders */
|
|
for (np = SHAPE_ORDS; np <= SHAPE_ORDS; np++) {
|
|
#endif
|
|
|
|
/* Fit to scattered data */
|
|
p->fit(p,
|
|
1, /* Vebose */
|
|
np, /* Number of curve parameters */
|
|
test_points, /* Test points */
|
|
pnts, /* Number of test points */
|
|
1.0 /* Smoothing */
|
|
);
|
|
|
|
printf("Residual = %f\n",p->resid);
|
|
printf("Total number of params = %d\n",p->luord);
|
|
for (i = 0; i < p->luord; i++) {
|
|
printf("Param %d = %f\n",i,p->pms[i]);
|
|
}
|
|
|
|
/* Display the result */
|
|
for (i = 0; i < XRES; i++) {
|
|
x = i/(double)(XRES-1);
|
|
xx[i] = x;
|
|
y1[i] = lin(x,xa,ya,pnts);
|
|
y2[i] = p->interp(p, x);
|
|
y = p->inv_interp(p, y2[i]);
|
|
if (fabs(x - y) > 0.00001)
|
|
printf("Inverse mismatch: %f -> %f -> %f\n",x,y2[i],y);
|
|
// if (y2[i] < -0.2)
|
|
// y2[i] = -0.2;
|
|
// else if (y2[i] > 1.2)
|
|
// y2[i] = 1.2;
|
|
}
|
|
do_plot(xx,y1,y2,NULL,XRES);
|
|
}
|
|
|
|
} /* next trial */
|
|
|
|
p->del(p);
|
|
|
|
return 0;
|
|
}
|
|
|
|
double lin(
|
|
double x,
|
|
double xa[],
|
|
double ya[],
|
|
int n) {
|
|
int i;
|
|
double y;
|
|
|
|
if (x < xa[0])
|
|
return ya[0];
|
|
else if (x > xa[n-1])
|
|
return ya[n-1];
|
|
|
|
for (i = 0; i < (n-1); i++)
|
|
if (x >=xa[i] && x <= xa[i+1])
|
|
break;
|
|
|
|
x = (x - xa[i])/(xa[i+1] - xa[i]);
|
|
|
|
y = ya[i] + (ya[i+1] - ya[i]) * x;
|
|
|
|
return y;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|