#include <stdio.h>	/* needed for assert. */
#include <assert.h>
#include <math.h>
#include "gpk_std.h"
#include "gpklib/bulsto.h"
#include "gpklib/ieee754.h"
#include "doublestore.h"

#define ACCURACY        1e-14

/*
return FALSE if total loss of significance on extrapolation
*/
BOOL rzextr(int iest, C double *x, C double *yin, double *yzero,
		double *yerror, int nv, int nuse, double **d)
{
/*
Use diagonal rational function extrapolation to evaluate nv functions at
x=0 by fitting a diagonal rational function to a sequence of estimates with
...
*/
 static doublestore fx;

 fx.alloc(nuse);
 assert((double *)fx  && d && x);
 assert(iest >= 0);
 if(iest == 0)	{
	int j;
	for(j=0;j<nv;j++)
		yerror[j] = d[j][0] = yzero[j] = yin[j];
	}
 else   {
	int j;
	int k;
    C int m1 = iest+1 < nuse ? iest+1 : nuse;
	for(k=0;k<m1-1;k++)
		fx[k+1] = x[iest-k-1]/x[iest];
	for(j=0;j<nv;j++)       {
 		double      yy, v, c;
		double ddy = quiet_nan(0);
                yy = yin[j];
		v = d[j][0];
                d[j][0] = c = yy;
		for(k=1;k<m1;k++)       {
 			double      b, b1;
                        b1 = fx[k] * v;
                        b = b1-c;
			if(fabs(b) > ACCURACY*fabs(b1)) {
                                b = (c-v)/b;
                                ddy = c*b;
                                c = b1*b;
				}
			else    {
                                ddy = v;
#                              ifdef DEBUG
				printf("%%\n");}
#                              endif
				}
                        if(k<m1-1)  v = d[j][k];
                        d[j][k] = ddy;
                        yy += ddy;
			}
                yerror[j] = ddy;
                yzero[j] = yy;
		}
	}
 return TRUE;
}
