#include <stdio.h>
#include <stdlib.h>
#include "kernel.h"
#include "vfpmath.h"

#define VFPSupport_CheckContext 0x58EC0
#define VFPSupport_CreateContext 0x58EC1
#define VFPSupport_DestroyContext 0x58EC2

extern double *swapend(double *x, int n);
extern double *fntable(double *x, int n, double (*fn)(double xx));
extern double *fnotable(double *x, double *y, int n, double (*fn)(double xx));
extern double *linrange(double *array, int n, double x, double y);
extern double *fnerror(double *array, double *exptd, int n);

double *x, *y, *exacty;
const double e=2.71828182845904523536;

int createctx(unsigned int flags, int regs, int *prev) {
  _kernel_swi_regs r;

  r.r[0]=flags;
  r.r[1]=regs;
  _kernel_swi(VFPSupport_CheckContext, &r, &r);
  flags|=(1<<31);
  r.r[0]=flags;
  r.r[2]=0;
  r.r[3]=0;
  _kernel_swi(VFPSupport_CreateContext, &r, &r);
  *prev=r.r[1];
  return(r.r[0]);
}

int destroyctx(int ctx, int prev) {
  _kernel_swi_regs r;

  r.r[0]=ctx;
  r.r[1]=prev;
  _kernel_swi(VFPSupport_DestroyContext, &r, &r);
  return(r.r[0]);
}

void testlog(void) {
  int i;
  double p, lp;
  
  linrange(x, 5, 0.0, 1.0);
  fnotable(exacty, y, 5, &vfp_ln);
  puts("Testing log2 function: known powers of e\n");
  for(i=0; i<=4; i++) {
    printf("%f: log=%12.10f\n", exacty[i], y[i]);
  }
  fnerror(y, x, 5);
  puts("Errors:\n");
  for(i=0; i<=4; i++) {
    printf("%f: error=%e\n", exacty[i], y[i]);
  }
  puts("Range reduction:\n");
  p=exacty[3];
  for(i=1; i<=10; i++) {
    p=p*e;
    lp=vfp_ln(p);
    printf("%d: log=%f, error=%e\n", i, lp, lp-i-0.75);
  }
}

void logvalues(double *lval) {
  double sr, fr;

  sr=vfp_sqrt(e);
  fr=vfp_sqrt(sr);
  lval[0]=1.0; lval[1]=fr;
  lval[2]=sr; lval[3]=sr*fr;
  lval[4]=e;
}

int main(void) {
  int ctx, savedctx;
  char nstring[24];
  
  ctx=createctx(1, 32, &savedctx);
  printf("Current context: %x; previous context: %x\n", ctx, savedctx);
  x=malloc(21*sizeof(double));
  y=x+7; exacty=x+14;
  logvalues(exacty);
  testlog();
  destroyctx(ctx, savedctx);
  return(0);
}

