1 /* A full-fledged interpolating lookup table implementation. */
3 #include <stdlib.h> /* malloc, free */
4 #include <stdio.h> /* printf */
5 #include <math.h> /* sin */
6 #include <assert.h> /* assert */
7 #include "tavl.h" /* tavl_* */
10 typedef struct evaluated_func_struct {
15 /* Comparison function for pointers to |evaluated_func_t|s.
16 |param| is not used. */
17 /* adjusted from compare_ints in test.c */
19 compare_evaluated_func_ts (const void *pa, const void *pb, void *param)
21 const evaluated_func_t *a = pa;
22 const evaluated_func_t *b = pb;
32 void *allocate_evaluated_func_t (double x, double f_of_x)
34 evaluated_func_t *eft=NULL;
35 eft = (evaluated_func_t *)malloc(sizeof(evaluated_func_t));
42 void free_evaluated_func_t (void *tavl_item, void *tavl_param)
48 interp_table_t *interp_table_allocate (interp_fn_t *fn, interp_tol_fn_t *tol)
50 interp_table_t *itable=NULL;
51 itable = (interp_table_t *)malloc(sizeof(interp_table_t));
52 assert(itable != NULL);
53 itable->table = (void *)tavl_create(&compare_evaluated_func_ts, NULL, NULL);
59 void interp_table_free (interp_table_t *itable)
61 tavl_destroy((struct tavl_table *)itable->table, &free_evaluated_func_t);
65 double interp_table_eval (interp_table_t *itable, void *params, double x)
67 struct tavl_table *table = (struct tavl_table *)itable->table;
68 const evaluated_func_t *a, *b, *c;
71 /* attempt to look up the x variable */
72 a = tavl_bracket(table, &x, (const void **)&b, (const void **)&c);
73 if (a != NULL) /* direct hit */
76 if (c == NULL || b == NULL) { /* out of interpolation range, run an actual eval */
77 y = (*itable->fn)(x, params);
78 tavl_insert(table, allocate_evaluated_func_t (x,y) );
80 //printf("bracketed x=%g with %g, %g\n", x, b->x, c->x);
81 /* should we interpolate? */
82 if ( (*itable->tol)(b->x, b->f_of_x, c->x, c->f_of_x) == 0 ) {
84 weight = (x - b->x) / (c->x - b->x);
85 y = b->f_of_x + (c->f_of_x - b->f_of_x)*weight;
86 //printf("interpolated f(%g) ~= %g\n", x, y);
87 //fprintf(stderr, "%g\t%g\n", x, y);
88 } else { /* tolerance exceeded, run an actual eval */
89 y = (*itable->fn)(x, params);
90 tavl_insert(table, allocate_evaluated_func_t (x,y) );