#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "sysdep.h"
#include "stack.h"
#include "output.h"
#include "builtin.h"
#include "funcs.h"
#include "linear.h"
#include "polynom.h"
#include "interval.h"
#include "spread.h"
#include "express.h"
#include "udf.h"
#include "mainloop.h"
#include "edit.h"
/***************************************************************************
* basic math functions (+, -, *, /) for real and complex numbers
*
***************************************************************************/
static void real_add (double *x, double *y, double *z)
{ *z=*x+*y;
}
static void complex_add (double *x, double *xi, double *y, double *yi,
double *z, double *zi)
{ *z=*x+*y;
*zi=*xi+*yi;
}
void add (header *hd, header *hd1)
/***** add
add the values elementwise.
*****/
{ spreadf2(real_add,complex_add,interval_add,hd);
}
static void real_subtract (double *x, double *y, double *z)
{ *z=*x-*y;
}
static void complex_subtract (double *x, double *xi, double *y, double *yi,
double *z, double *zi)
{ *z=*x-*y;
*zi=*xi-*yi;
}
void subtract (header *hd, header *hd1)
/***** substract
substract the values elementwise.
*****/
{ spreadf2(real_subtract,complex_subtract,interval_sub,hd);
}
static void real_multiply (double *x, double *y, double *z)
{ *z=*x*(*y);
}
void complex_multiply (double *x, double *xi, double *y, double *yi,
double *z, double *zi)
{ double h=*x * *y - *xi * *yi;
*zi=*x * *yi + *xi * *y;
*z=h;
}
void dotmultiply (header *hd, header *hd1)
/***** dotmultiply
multiply the values elementwise.
*****/
{ spreadf2(real_multiply,complex_multiply,interval_mult,hd);
}
static void real_divide (double *x, double *y, double *z)
{
#ifdef FLOAT_TEST
if (*y==0.0) { *y=1e-10; error=1; }
#endif
*z=*x/(*y);
}
void complex_divide (double *x, double *xi, double *y, double *yi,
double *z, double *zi)
{ double r,h;
r=*y * *y + *yi * *yi;
#ifdef FLOAT_TEST
if (r==0) { r=1e-10; error=1; }
#endif
h=(*x * *y + *xi * *yi)/r;
*zi=(*xi * *y - *x * *yi)/r;
*z=h;
}
void dotdivide (header *hd, header *hd1)
/***** dotdivide
divide the values elementwise.
*****/
{ spreadf2(real_divide,complex_divide,interval_div,hd);
}
void copy_complex (double *x, double *y)
{ *x++=*y++;
*x=*y;
}
/***************************************************************************
* math functions (exp, log, sqr, sin, cos, tan, asin, acos, atan)
*
***************************************************************************/
static void csin (double *x, double *xi, double *z, double *zi)
{ *z=cosh(*xi)*sin(*x);
*zi=sinh(*xi)*cos(*x);
}
void msin (header *hd)
{ spread1i(sin,csin,isin,hd);
test_error("sin");
}
static void ccos (double *x, double *xi, double *z, double *zi)
{ *z=cosh(*xi)*cos(*x);
*zi=-sinh(*xi)*sin(*x);
}
void mcos (header *hd)
{ spread1i(cos,ccos,icos,hd);
test_error("cos");
}
static void ctan (double *x, double *xi, double *z, double *zi)
{ double s,si,c,ci;
csin(x,xi,&s,&si); ccos(x,xi,&c,&ci);
complex_divide(&s,&si,&c,&ci,z,zi);
}
#ifdef FLOAT_TEST
static double rtan (double x)
{ if (cos(x)==0.0) return 1e10;
return tan(x);
}
#endif
void mtan (header *hd)
{ spread1i(
#ifdef FLOAT_TEST
rtan,
#else
tan,
#endif
ctan,itan,hd);
test_error("tan");
}
#ifdef FLOAT_TEST
static double ratan (double x)
{ if (x<=-M_PI && x>=M_PI) return 1e10;
else return atan(x);
}
#endif
static void carg (double *x, double *xi, double *z)
{
#ifdef FLOAT_TEST
if (*x==0.0 && *xi==0.0) *z=0.0;
#endif
*z = atan2(*xi,*x);
}
#ifdef FLOAT_TEST
static double rlog (double x)
{ if (x<=0) { error=1; return 0; }
else return log(x);
}
#endif
static void cclog (double *x, double *xi, double *z, double *zi)
{
#ifdef FLOAT_TEST
*z=rlog(sqrt(*x * *x + *xi * *xi));
#else
*z=log(sqrt(*x * *x + *xi * *xi));
#endif
carg(x,xi,zi);
}
static void catan (double *x, double *xi, double *y, double *yi)
{ double h,hi,g,gi,t,ti;
h=1-*xi; hi=*x; g=1+*xi; gi=-*x;
complex_divide(&h,&hi,&g,&gi,&t,&ti);
cclog(&t,&ti,&h,&hi);
*y=hi/2; *yi=-h/2;
}
void matan (header *hd)
{ spread1i(
#ifdef FLOAT_TEST
ratan,
#else
atan,
#endif
catan,iatan,hd);
test_error("atan");
}
#ifdef FLOAT_TEST
static double rasin (double x)
{ if (x<-1 || x>1) { error=1; return 0; }
else return asin(x);
}
#endif
static void csqrt (double *x, double *xi, double *z, double *zi)
{ double a,r;
carg(x,xi,&a); a=a/2.0;
r=sqrt(sqrt(*x * *x + *xi * *xi));
*z=r*cos(a);
*zi=r*sin(a);
}
static void casin (double *x, double *xi, double *y, double *yi)
{ double h,hi,g,gi;
complex_multiply(x,xi,x,xi,&h,&hi);
h=1-h; hi=-hi;
csqrt(&h,&hi,&g,&gi);
h=-*xi+g; hi=*x+gi;
cclog(&h,&hi,yi,y);
*yi=-*yi;
}
void masin (header *hd)
{ spread1(
#ifdef FLOAT_TEST
rasin,
#else
asin,
#endif
casin,hd);
test_error("asin");
}
#ifdef FLOAT_TEST
static double racos (double x)
{ if (x<-1 || x>1) { error=1; return 0; }
else return acos(x);
}
#endif
static void cacos (double *x, double *xi, double *y, double *yi)
{ double h,hi,g,gi;
complex_multiply(x,xi,x,xi,&h,&hi);
h=1-h; hi=-hi;
csqrt(&h,&hi,&g,&gi);
hi=*xi+g; h=*x-gi;
cclog(&h,&hi,yi,y);
*yi=-*yi;
}
void macos (header *hd)
{ spread1(
#ifdef FLOAT_TEST
racos,
#else
acos,
#endif
cacos,hd);
test_error("acos");
}
static void cexp (double *x, double *xi, double *z, double *zi)
{ double r=exp(*x);
*z=cos(*xi)*r;
*zi=sin(*xi)*r;
}
#ifdef FLOAT_TEST
static void rcexp (double *x, double *xi, double *z, double *zi)
{ double r;
if (*x>=1000) { error=1; return; }
r=exp(*x);
*z=cos(*xi)*r;
*zi=sin(*xi)*r;
}
#endif
static inline double rexp (double x)
{ if (x>=1000) { error=1; return 0; }
else return exp(x);
}
void mexp (header *hd)
{
#ifdef FLOAT_TEST
spread1i(rexp,rcexp,iexp,hd);
#else
spread1i(exp,cexp,iexp,hd);
#endif
test_error("exp");
}
static double rarg (double x)
{ if (x>=0) return 0.0;
else return M_PI;
}
void mlog (header *hd)
{
#ifdef FLOAT_TEST
spread1i(rlog,cclog,ilog,hd);
#else
spread1i(log,cclog,ilog,hd);
#endif
test_error("log");
}
#ifdef FLOAT_TEST
static double rsqrt (double x)
{ if (x<0.0) { error=1; return 0; }
else return sqrt(x);
}
#endif
void msqrt (header *hd)
{ spread1i(
#ifdef FLOAT_TEST
rsqrt,
#else
sqrt,
#endif
csqrt,isqrt,hd);
test_error("sqrt");
}
static void rrem (double *x, double *n, double *y)
{
*y=fmod(*x,*n);
}
void mrem (header *hd)
{ spreadf2(rrem,0,0,hd);
test_error("mod");
}
static void rmod (double *x, double *n, double *y)
{
if (*n==0.0)
*y=*x;
else {
*y=fmod(*x,*n);
if (*y<0) *y+=*n;
}
}
void mmod (header *hd)
{ spreadf2(rmod,0,0,hd);
test_error("mod");
}
static void cpow (double *x, double *xi, double *y, double *yi,
double *z, double *zi)
{ double l,li,w,wi;
if (fabs(*x)<epsilon && fabs(*xi)<epsilon)
{ *z=*zi=0.0; return;
}
cclog(x,xi,&l,&li);
complex_multiply(y,yi,&l,&li,&w,&wi);
cexp(&w,&wi,z,zi);
}
static void rpow (double *x, double *y, double *z)
{ int n;
if (*x>0.0) *z=pow(*x,*y);
else if (*x==0.0) if (*y==0.0) *z=1.0; else *z=0.0;
else
{ n=(int)*y;
if (n!=*y)
{ output("Illegal argument for ^\n"); error=1;
return;
}
if (n%2) *z=-pow(-*x,n);
else *z=pow(-*x,n);
}
}
void mpower (header *hd)
{ spreadf2(rpow,cpow,ipow,hd);
test_error("^");
}
/****************************************************************************
* degree, sign, ceil, floor functions
*
****************************************************************************/
static double rdegree (double x)
{ return x/180*M_PI;
}
void mdegree (header *hd)
{ spread1(rdegree,0,hd);
test_error("signum");
}
static double rsign (double x)
{ if (x<0) return -1;
else if (x<=0) return 0;
else return 1;
}
void msign (header *hd)
{ spread1(rsign,0,hd);
test_error("sign");
}
void mceil (header *hd)
{ spread1(ceil,0,hd);
test_error("ceil");
}
void mfloor (header *hd)
{ spread1(floor,0,hd);
test_error("floor");
}
static double rounder;
static double rround (double x)
{ x*=rounder;
if (x>0) x=floor(x+0.5);
else x=-floor(-x+0.5);
return x/rounder;
}
static void cround (double *x, double *xi, double *z, double *zi)
{ *z=rround(*x);
*zi=rround(*xi);
}
static double frounder[]={1.0,10.0,100.0,1000.0,10000.0,100000.0,1000000.0,
10000000.0,100000000.0,1000000000.0,10000000000.0};
void mround (header *hd)
{ header *hd1;
int n;
hd1=next_param(hd);
if (hd1) hd1=getvalue(hd1); if (error) return;
if (hd1->type!=s_real) wrong_arg_in("round");
n=(int)(*realof(hd1));
if (n>0 && n<11) rounder=frounder[n];
else rounder=pow(10.0,n);
spread1(rround,cround,hd);
test_error("round");
}
/****************************************************************************
* complex specific functions
*
****************************************************************************/
static void cconj (double *x, double *xi, double *z, double *zi)
{ *zi=-*xi; *z=*x;
}
static double ident (double x)
{ return x;
}
void mconj (header *hd)
{ spread1(ident,cconj,hd);
test_error("conj");
}
static void crealpart (double *x, double *xi, double *z)
{ *z=*x;
}
void mre (header *hd)
{ spread1r(ident,crealpart,hd);
test_error("re");
}
static double zero (double x)
{ return 0.0;
}
static void cimagpart (double *x, double *xi, double *z)
{ *z=*xi;
}
void mim (header *hd)
{ spread1r(zero,cimagpart,hd);
test_error("im");
}
void marg (header *hd)
{ spread1r(rarg,carg,hd);
test_error("arg");
}
static void cxabs (double *x, double *xi, double *z)
{ *z=sqrt(*x * *x + *xi * *xi);
}
void mabs (header *hd)
{ spread1ir(fabs,cxabs,iabs,hd);
test_error("abs");
}
/****************************************************************************
* constants
*
****************************************************************************/
void mpi (header *hd)
{ new_real(M_PI,"");
}
void margn (header *hd)
{ new_real(actargn,"");
}
void mtime (header *hd)
{ new_real(myclock(),"");
}
void mfree (header *hd)
{ new_real(ramend-endlocal,"");
}
#ifndef NOSHRINK
void mshrink (header *hd)
{ header *st=hd,*result;
unsigned long size;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_real) wrong_arg_in("shrink");
if (*realof(hd)>LONG_MAX) wrong_arg_in("shrink");
size=(unsigned long)*realof(hd);
if (ramend-size<newram)
{ output("Cannot shrink that much!\n");
error=171; return;
}
if (size)
{ if (shrink(size)) ramend-=size;
else
{ output("Shrink failed!\n"); error=172; return;
}
}
result=new_real(ramend-ramstart,"");
moveresult(st,result);
}
#endif
void mepsilon (header *hd)
{ new_real(epsilon,"");
}
void msetepsilon (header *hd)
{ header *stack=hd,*hd1,*result;
hd1=getvalue(hd); if (error) return;
if (hd1->type!=s_real) wrong_arg_in("setepsilon");
result=new_real(epsilon,"");
changedepsilon=epsilon=*realof(hd1);
moveresult(stack,result);
}
void mlocalepsilon (header *hd)
{ header *stack=hd,*hd1,*result;
hd1=getvalue(hd); if (error) return;
if (hd1->type!=s_real) wrong_arg_in("localepsilon");
result=new_real(epsilon,"");
epsilon=*realof(hd1);
moveresult(stack,result);
}
void mtype (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd); if (error) return;
result=new_real(hd->type,"");
moveresult(st,result);
}
void mintersects (header *hd)
{ spreadf2r(0,0,iintersects,hd);
test_error("intersects");
}
/****************************************************************************
* compare operator
*
****************************************************************************/
static void rgreater (double *x, double *y, double *z)
{ if (*x>*y) *z=1.0;
else *z=0.0;
}
static void igreater (double *xa, double *xb, double *ya, double *yb,
double *z)
{ if (*xa>*yb) *z=1.0;
else *z=0.0;
}
void mgreater (header *hd)
{ header *st=hd,*hd1,*result,*hdv;
hdv=getvariable(hd);
if (hdv->type==s_string)
{ hd=getvalue(hd);
hd1=getvalue(nextof(st)); if (error) return;
if (hd1->type!=s_string) wrong_arg_in("==");
result=new_real(strcmp(stringof(hd),stringof(hd1))>0,"");
moveresult(st,result);
}
else spreadf2r(rgreater,0,igreater,st);
test_error("==");
}
static void rless (double *x, double *y, double *z)
{ if (*x<*y) *z=1.0;
else *z=0.0;
}
static void ilesst (double *xa, double *xb, double *ya, double *yb,
double *z)
{ if (*xb<*ya) *z=1.0;
else *z=0.0;
}
void mless (header *hd)
{ header *st=hd,*hd1,*result,*hdv;
hdv=getvariable(hd);
if (hdv->type==s_string)
{ hd=getvalue(hd);
hd1=getvalue(nextof(st)); if (error) return;
if (hd1->type!=s_string) wrong_arg_in("==");
result=new_real(strcmp(stringof(hd),stringof(hd1))<0,"");
moveresult(st,result);
}
else spreadf2r(rless,0,ilesst,st);
test_error("<");
}
static void rgreatereq (double *x, double *y, double *z)
{ if (*x>=*y) *z=1.0;
else *z=0.0;
}
static void igreatereq (double *xa, double *xb, double *ya, double *yb, double *z)
{ if (*xa>=*yb) *z=1.0;
else *z=0.0;
}
void mgreatereq (header *hd)
{ header *st=hd,*hd1,*result,*hdv;
hdv=getvariable(hd);
if (hdv->type==s_string)
{ hd=getvalue(hd);
hd1=getvalue(nextof(st)); if (error) return;
if (hd1->type!=s_string) wrong_arg_in("==");
result=new_real(strcmp(stringof(hd),stringof(hd1))>=0,"");
moveresult(st,result);
}
else spreadf2r(rgreatereq,0,igreatereq,st);
test_error(">=");
}
static void rlesseq (double *x, double *y, double *z)
{ if (*x<=*y) *z=1.0;
else *z=0.0;
}
static void ilesseq (double *xa, double *xb, double *ya, double *yb,
double *z)
{ if (*xb<=*ya) *z=1.0;
else *z=0.0;
}
void mlesseq (header *hd)
{ header *st=hd,*hd1,*result,*hdv;
hdv=getvariable(hd);
if (hdv->type==s_string)
{ hd=getvalue(hd);
hd1=getvalue(nextof(st)); if (error) return;
if (hd1->type!=s_string) wrong_arg_in("==");
result=new_real(strcmp(stringof(hd),stringof(hd1))<=0,"");
moveresult(st,result);
}
else spreadf2r(rlesseq,0,ilesseq,st);
test_error("<=");
}
static void requal (double *x, double *y, double *z)
{ if (*x==*y) *z=1.0;
else *z=0.0;
}
static void cequal (double *x, double *xi, double *y, double *yi, double *z)
{ if (*x==*y && *xi==*yi) *z=1.0;
else *z=0.0;
}
void mequal (header *hd)
{ header *st=hd,*hd1,*result,*hdv;
hdv=getvariable(hd);
if (hdv->type==s_string)
{ hd=getvalue(hd);
hd1=getvalue(nextof(st)); if (error) return;
if (hd1->type!=s_string) wrong_arg_in("==");
result=new_real(strcmp(stringof(hd),stringof(hd1))==0,"");
moveresult(st,result);
}
else spreadf2r(requal,cequal,cequal,st);
test_error("==");
}
static void runequal (double *x, double *y, double *z)
{ if (*x!=*y) *z=1.0;
else *z=0.0;
}
static void cunequal (double *x, double *xi, double *y, double *yi, double *z)
{ if (*x!=*y || *xi!=*yi) *z=1.0;
else *z=0.0;
}
static void iunequal (double *x, double *xi, double *y, double *yi, double *z)
{ if (*x!=*y || *xi!=*yi) *z=1.0;
else *z=0.0;
}
void munequal (header *hd)
{ header *st=hd,*hd1,*result,*hdv;
hdv=getvariable(hd);
if (hdv->type==s_string)
{ hd=getvalue(hd);
hd1=getvalue(nextof(st)); if (error) return;
if (hd1->type!=s_string) wrong_arg_in("==");
result=new_real(strcmp(stringof(hd),stringof(hd1))!=0,"");
moveresult(st,result);
}
else spreadf2r(runequal,cunequal,iunequal,st);
test_error("<>");
}
static void raboutequal (double *x, double *y, double *z)
{ double rx=fabs(*x),ry=fabs(*y);
if (rx<epsilon)
{ if (ry<epsilon) *z=1.0;
else *z=0.0;
}
else if (ry<epsilon)
{ if (rx<epsilon) *z=1.0;
else *z=0.0;
}
else if (fabs(*x-*y)/rx<epsilon) *z=1.0;
else *z=0.0;
}
static void caboutequal
(double *x, double *xi, double *y, double *yi, double *z)
{ raboutequal(x,y,z);
if (*z!=0.0) raboutequal(xi,yi,z);
}
static void iaboutequal (double *x, double *xi, double *y, double *yi, double *z)
{ raboutequal(x,y,z);
if (*z!=0.0) raboutequal(xi,yi,z);
}
void maboutequal (header *hd)
{ spreadf2r(raboutequal,caboutequal,iaboutequal,hd);
test_error("~=");
}
/****************************************************************************
* logical operators
*
****************************************************************************/
static void ror (double *x, double *y, double *z)
{ if (*x!=0.0 || *y!=0.0) *z=1.0;
else *z=0.0;
}
void mor (header *hd)
{ spreadf2(ror,0,ior,hd);
test_error("||");
}
static void rrand (double *x, double *y, double *z)
{ if (*x!=0.0 && *y!=0.0) *z=1.0;
else *z=0.0;
}
void mand (header *hd)
{ spreadf2(rrand,0,iand,hd);
test_error("&&");
}
static double rnot (double x)
{ if (x!=0.0) return 0.0;
else return 1.0;
}
static void cnot (double *x, double *xi, double *r)
{ if (*x==0.0 && *xi==0.0) *r=1.0;
else *r=0.0;
}
void mnot (header *hd)
{ spread1r(rnot,cnot,hd);
test_error("!");
}
/****************************************************************************
* matrix operators
*
****************************************************************************/
void mcomplex (header *hd)
{ header *st=hd,*result;
double *m,*mr;
long i,n;
int c,r;
hd=getvalue(hd);
if (hd->type==s_matrix)
{ getmatrix(hd,&r,&c,&m);
result=new_cmatrix(r,c,""); if (error) return;
n=(long)r*c;
mr=matrixof(result)+(long)2*(n-1);
m+=n-1;
for (i=0; i<n; i++)
{ *mr=*m--; *(mr+1)=0.0; mr-=2;
}
moveresult(st,result);
}
else if (hd->type==s_real)
{ result=new_complex(*realof(hd),0.0,""); if (error) return;
moveresult(st,result);
}
}
/***************************************************************************
* events handling
*
***************************************************************************/
void mwait (header *hd)
{ header *st=hd,*result;
double now;
int h;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_real) wrong_arg_in("wait");
now=myclock();
sys_wait(*realof(hd),&h);
if (h==escape) { output("Interrupt\n"); error=1; return; }
now=myclock()-now;
if (now>*realof(hd)) now=*realof(hd);
result=new_real(now,"");
if (error) return;
moveresult(st,result);
}
void mkey (header *hd)
{ int scan,key;
key=wait_key(&scan);
if (scan==escape) { output("Interrupt\n"); error=1; return; }
if (key) new_real(key,"");
else new_real(scan,"");
}
void mcode (header *hd)
{ new_real(test_code(),"");
}
void minput (header *hd)
{ header *st=hd,*result;
char input[1024],*oldnext;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("input");
retry: output(stringof(hd)); output("? ");
nojump=1;
edit(input);
stringon=1;
oldnext=next; next=input; result=scan_value(); next=oldnext;
stringon=0;
if (error)
{ output("Error in input!\n"); error=0; goto retry;
}
moveresult(st,result);
}
void mlineinput (header *hd)
{ header *st=hd,*result;
char input[1024];
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("lineinput");
nojump=1;
output(stringof(hd)); output("? ");
edit(input);
result=new_string(input,strlen(input),"");
moveresult(st,result);
}
void minterpret (header *hd)
{ header *st=hd,*result;
char *oldnext;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("interpret");
stringon=1;
oldnext=next; next=stringof(hd); result=scan(); next=oldnext;
stringon=0;
if (error) { result=new_string("Error",8,""); error=0; }
moveresult(st,result);
}
void mevaluate (header *hd)
{ header *st=hd,*result;
char *oldnext;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("evaluate");
stringon=1;
oldnext=next; next=stringof(hd); result=scan(); next=oldnext;
stringon=0;
if (error) { result=new_string("Syntax error!",16,""); }
moveresult(st,result);
}
/***************************************************************************
* statistics - random numbers
*
***************************************************************************/
void mfastrandom (header *hd)
{ header *st=hd,*result;
double *m;
int r,c;
long k,n;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_matrix || dimsof(hd)->r!=1 || dimsof(hd)->c!=2
|| *(m=matrixof(hd))<0 || *m>=INT_MAX
|| *(m+1)<0 || *(m+1)>INT_MAX)
wrong_arg_in("random");
r=(int)*m;
c=(int)*(m+1);
result=new_matrix(r,c,""); if (error) return;
m=matrixof(result);
n=(long)c*r;
for (k=0; k<n; k++) *m++=(double)rand()/(double)RAND_MAX;
moveresult(st,result);
}
void mnormal (header *hd)
{ header *st=hd,*result;
double *m,r1,r2;
int r,c;
long k,n;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_matrix || dimsof(hd)->r!=1 || dimsof(hd)->c!=2
|| *(m=matrixof(hd))<0 || *m>=INT_MAX
|| *(m+1)<0 || *(m+1)>INT_MAX)
wrong_arg_in("normal");
r=(int)*m;
c=(int)*(m+1);
result=new_matrix(r,c,""); if (error) return;
m=matrixof(result);
n=(long)c*r;
for (k=0; k<n; k++)
{ r1=(double)rand()/(double)RAND_MAX;
if (r1==0.0) *m++=0.0;
else
{ r2=(double)rand()/(double)RAND_MAX;
*m++=sqrt(-2*log(r1))*cos(2*M_PI*r2);
}
}
moveresult(st,result);
}
static double rfak (double x)
{ int i,n;
double res=1;
if (x<2 || x>INT_MAX) return 1.0;
n=(int)x;
for (i=2; i<=n; i++) res=res*i;
return res;
}
void mfak (header *hd)
{ spread1(rfak,0,hd);
test_error("fak");
}
static double rlogfak (double x)
{ int i,n;
double res=0;
if (x<2 || x>INT_MAX) return 0.0;
n=(int)x;
for (i=2; i<=n; i++) res=res+log(i);
return res;
}
void mlogfak (header *hd)
{ spread1(rlogfak,0,hd);
test_error("logfak");
}
static void rbin (double *x, double *y, double *z)
{ long i,n,m,k;
double res;
n=(long)*x; m=(long)*y;
if (m<=0) *z=1.0;
else
{ res=k=n-m+1;
for (i=2; i<=m; i++) { k++; res=res*k/i; }
*z=res;
}
}
void mbin (header *hd)
{ spreadf2(rbin,0,0,hd);
test_error("bin");
}
static void rlogbin (double *x, double *y, double *z)
{ long i,n,m,k;
double res;
n=(long)*x; m=(long)*y;
if (m<=0) *z=0.0;
else
{ k=n-m+1;
res=log(n-m+1);
for (i=2; i<=m; i++) { k++; res+=log(k)-log(i); }
*z=res;
}
}
void mlogbin (header *hd)
{ spreadf2(rlogbin,0,0,hd);
test_error("bin");
}
static void rtd (double *xa, double *yf, double *zres)
{ double t,t1,a,b,h,z,p,y,x;
int flag=0;
if (fabs(*xa)<epsilon) { *zres=0.5; return; }
if (*xa<0) flag=1;
t=*xa * *xa;
if (t>=1) { a=1; b=*yf; t1=t; }
else { a=*yf; b=1; t1=1/t; }
y=2/(9*a); z=2/(9*b);
h=pow(t1,1.0/3);
x=fabs((1-z)*h-1+y)/sqrt(z*h*h+y);
if (b<4) x=x*(1+0.08*x*x*x*x/(b*b*b));
h=1+x*(0.196854+x*(0.115194+x*(0.000344+x*0.019527)));
p=0.5/(h*h*h*h);
if (t<0.5) *zres=p/2+0.5;
else *zres=1-p/2;
if (flag) *zres=1-*zres;
}
void mtd (header *hd)
{ spreadf2(rtd,0,0,hd);
test_error("tdis");
}
static double invgauss (double a)
{ double t,c,d;
int flag=0;
if (a<0.5) { a=1-a; flag=1; }
t=sqrt(-2*log(fabs(1-a)));
c=2.515517+t*(0.802853+t*0.010328);
d=1+t*(1.432788+t*(0.189269+t*0.001308));
if (flag) return (c/d-t);
else return t-c/d;
}
void minvgauss (header *hd)
{ spread1(invgauss,0,hd);
test_error("invnormaldis");
}
static void invrtd (double *x, double *y, double *zres)
{ double z=*x,f=*y,g1,g2,g3,g4,z2;
int flag=0;
if (z<0.5) { flag=1; z=1-z; }
z=invgauss(z);
z2=z*z;
g1=z*(1+z2)/4.0;
g2=z*(3+z2*(16+5*z2))/96.0;
g3=z*(-15+z2*(17+z2*(19+z2*3)))/384.0;
g4=z*(-945+z2*(-1920+z2*(1482+z2*(776+z2*79))))/92160.0;
*zres=(((g4/f+g3)/f+g2)/f+g1)/f+z;
if (flag) *zres=-*zres;
}
void minvtd (header *hd)
{ spreadf2(invrtd,0,0,hd);
test_error("invtdis");
}
static void chi (double *xa, double *yf, double *zres)
{ double ch=*xa,x,y,s,t,g,j=1;
long i,p,f;
f=(long)*yf;
if (ch<epsilon) { *zres=0.0; return; }
p=(f+1)/2;
for (i=f; i>=2; i-=2) j=j*i;
x=pow(ch,p)*exp(-(ch/2))/j;
if (f%2==0) y=1;
else y=sqrt(2/(ch*M_PI));
s=1; t=1; g=f;
while (t>1e-5)
{ g=g+2;
t=t*ch/g;
s=s+t;
}
*zres=x*y*s;
}
void mchi (header *hd)
{ spreadf2(chi,0,0,hd);
test_error("chidis");
}
static double f1,f2;
static double rfd (double F)
{ double f0,a,b,h,z,p,y,x;
if (F<epsilon) return 0.0;
if (F<1) { a=f2; b=f1; f0=1/F; }
else { a=f1; b=f2; f0=F; }
y=2/(9*a); z=2/(9*b);
h=pow(f0,1.0/3);
x=fabs((1-z)*h-1+y)/sqrt(z*h*h+y);
if (b<4) x=x*(1+0.08*x*x*x*x/(b*b*b));
h=1+x*(0.196854+x*(0.115194+x*(0.000344+x*0.019527)));
p=0.5/(h*h*h*h);
if (F>=1) return 1-p;
else return p;
}
void mfdis (header *hd)
{ header *st=hd,*hd1,*hd2=0;
hd1=next_param(st);
if (hd1)
{ hd2=next_param(hd1);
hd1=getvalue(hd1);
}
if (hd2) hd2=getvalue(hd2);
if (error) return;
if (hd1->type!=s_real || hd2->type!=s_real) wrong_arg_in("fdis");
f1=*realof(hd1);
f2=*realof(hd2);
spread1(rfd,0,hd);
test_error("fdis");
}
/*****************************************************************************
* sorting
*
*****************************************************************************/
static void rmax (double *x, double *y, double *z)
{ if (*x>*y) *z=*x;
else *z=*y;
}
void mmax (header *hd)
{ spreadf2(rmax,0,imax,hd);
test_error("max");
}
static void rmin (double *x, double *y, double *z)
{ if (*x>*y) *z=*y;
else *z=*x;
}
void mmin (header *hd)
{ spreadf2(rmin,0,imin,hd);
test_error("min");
}
typedef struct { double val; int ind; } sorttyp;
static int sorttyp_compare (const sorttyp *x, const sorttyp *y)
{ if (x->val>y->val) return 1;
else if (x->val==y->val) return 0;
else return -1;
}
void msort (header *hd)
{ header *st=hd,*result,*result1;
double *m,*m1;
sorttyp *t;
int r,c,i;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_real && hd->type!=s_matrix) wrong_arg_in("sort");
getmatrix(hd,&r,&c,&m);
if (c==1 || r==1) result=new_matrix(r,c,"");
else wrong_arg_in("sort");
if (error) return;
result1=new_matrix(r,c,"");
if (error) return;
if (c==1) c=r;
if (c==0) wrong_arg_in("sort");
if (!freeram(c*sizeof(sorttyp)))
{ output("Out of memory!\n"); error=600; return;
}
t=(sorttyp *)newram;
for (i=0; i<c; i++)
{ t->val=*m++; t->ind=i; t++;
}
qsort(newram,c,sizeof(sorttyp),
(int (*) (const void *, const void *))sorttyp_compare);
m=matrixof(result); m1=matrixof(result1);
t=(sorttyp *)newram;
for (i=0; i<c; i++)
{ *m++=t->val; *m1++=t->ind+1; t++;
}
moveresult(st,result);
moveresult(nextof(st),result1);
}
void mstatistics (header *hd)
{ header *st=hd,*hd1,*result;
int i,n,r,c,k;
double *m,*mr;
hd=getvalue(hd);
hd1=next_param(st);
if (hd1) hd1=getvalue(hd1); if (error) return;
if (hd1->type!=s_real || hd->type!=s_matrix) wrong_arg_in("count");
if (*realof(hd1)>INT_MAX || *realof(hd1)<2) wrong_arg_in("count");
n=(int)*realof(hd1);
getmatrix(hd,&r,&c,&m);
if (r!=1 && c!=1) wrong_arg_in("count");
if (c==1) c=r;
result=new_matrix(1,n,""); if (error) return;
mr=matrixof(result); for (i=0; i<n; i++) *mr++=0.0;
mr=matrixof(result);
for (i=0; i<c; i++)
{ if (*m>=0 && *m<n)
{ k=(int)floor(*m);
mr[k]+=1.0;
}
m++;
}
moveresult(st,result);
}
void mmax1 (header *hd)
{ header *result,*st=hd;
double x,*m,*mr,max,max1;
int r,c,i,j;
hd=getvalue(hd); if (error) return;
if (hd->type==s_real || hd->type==s_matrix)
{ getmatrix(hd,&r,&c,&m);
result=new_matrix(r,1,""); if (error) return;
mr=matrixof(result);
for (i=0; i<r; i++)
{ max=*m++;
for (j=1; j<c; j++)
{ x=*m++;
if (x>max) max=x;
}
*mr++=max;
}
}
else if (hd->type==s_interval || hd->type==s_imatrix)
{ getmatrix(hd,&r,&c,&m);
result=new_imatrix(r,1,""); if (error) return;
mr=matrixof(result);
for (i=0; i<r; i++)
{ max=*m++;
max1=*m++;
for (j=1; j<c; j++)
{ imax(&max,&max1,m,m+1,&max,&max1);
m+=2;
}
*mr++=max;
*mr++=max1;
}
}
else wrong_arg_in("max");
moveresult(st,result);
}
void mmin1 (header *hd)
{ header *result,*st=hd;
double x,*m,*mr,max,max1;
int r,c,i,j;
hd=getvalue(hd); if (error) return;
if (hd->type==s_real || hd->type==s_matrix)
{ getmatrix(hd,&r,&c,&m);
result=new_matrix(r,1,""); if (error) return;
mr=matrixof(result);
for (i=0; i<r; i++)
{ max=*m; m++;
for (j=1; j<c; j++)
{ x=*m++;
if (x<max) max=x;
}
*mr++=max;
}
}
else if (hd->type==s_interval || hd->type==s_imatrix)
{ getmatrix(hd,&r,&c,&m);
result=new_imatrix(r,1,""); if (error) return;
mr=matrixof(result);
for (i=0; i<r; i++)
{ max=*m++;
max1=*m++;
for (j=1; j<c; j++)
{ imin(&max,&max1,m,m+1,&max,&max1);
m+=2;
}
*mr++=max;
*mr++=max1;
}
}
else wrong_arg_in("min");
moveresult(st,result);
}
/****************************************************************************
* types
*
****************************************************************************/
void miscomplex (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd);
if (hd->type==s_complex || hd->type==s_cmatrix)
result=new_real(1.0,"");
else result=new_real(0.0,"");
if (error) return;
moveresult(st,result);
}
void misreal (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd); if (error) return;
if (hd->type==s_real || hd->type==s_matrix)
result=new_real(1.0,"");
else result=new_real(0.0,"");
if (error) return;
moveresult(st,result);
}
void misfunction (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd); if (error) return;
if (hd->type==s_string
&& (searchudf(stringof(hd))!=0 || find_builtin(stringof(hd))!=0))
result=new_real(1.0,"");
else result=new_real(0.0,"");
if (error) return;
moveresult(st,result);
}
void misvar (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd); if (error) return;
if (hd->type==s_string
&& searchvar(stringof(hd))!=0)
result=new_real(1.0,"");
else result=new_real(0.0,"");
if (error) return;
moveresult(st,result);
}
void misinterval (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd); if (error) return;
if (hd->type==s_interval || hd->type==s_imatrix)
result=new_real(1.0,"");
else result=new_real(0.0,"");
if (error) return;
moveresult(st,result);
}
/****************************************************************************
* rounding
*
****************************************************************************/
void mchar (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_real) wrong_arg_in("char");
result=new_string("a",1,""); if (error) return;
*stringof(result)=(char)*realof(hd);
moveresult(st,result);
}
void mascii (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("ascii");
result=new_real(*stringof(hd),""); if (error) return;
moveresult(st,result);
}
void merror (header *hd)
{ hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("error");
output1("Error : %s\n",stringof(hd));
error=301;
}
extern int preventoutput;
void merrlevel (header *hd)
{ header *st=hd,*res;
char *oldnext;
int en;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("errorlevel");
stringon=1;
oldnext=next; next=stringof(hd);
res=new_real(0,"");
preventoutput=1;
scan();
preventoutput=0;
next=oldnext;
stringon=0;
en=error; error=0;
if (en)
{ *realof(res)=en;
moveresult(st,res);
}
else
{ moveresult1(st,res);
}
}
void mprintf (header *hd)
{ header *st=hd,*hd1,*result;
char string[1024];
hd1=next_param(hd);
hd=getvalue(hd);
hd1=getvalue(hd1); if (error) return;
if (hd->type!=s_string || hd1->type!=s_real)
wrong_arg_in("printf");
sprintf(string,stringof(hd),*realof(hd1));
result=new_string(string,strlen(string),""); if (error) return;
moveresult(st,result);
}
void msetkey (header *hd)
/*****
set a function key
*****/
{ header *st=hd,*hd1,*result;
char *p;
int n;
hd=getvalue(hd); if (error) return;
hd1=nextof(st); hd1=getvalue(hd1); if (error) return;
if (hd->type!=s_real || hd1->type!=s_string) wrong_arg_in("setkey");
n=(int)(*realof(hd))-1; p=stringof(hd1);
if (n<0 || n>=10 || strlen(p)>63) wrong_arg_in("setkey");
result=new_string(fktext[n],strlen(fktext[n]),"");
if (error) return;
strcpy(fktext[n],p);
moveresult(st,result);
}
void mcd (header *hd)
{ header *st=hd,*result;
char *path;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("cd");
path=cd(stringof(hd));
result=new_string(path,strlen(path),"");
moveresult(st,result);
}
static char **search_entries=NULL;
static int search_count=0,search_current=0;
void mdir (header *hd)
{ header *st=hd,*result;
// char *name;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("dir");
if (search_entries) {
int i;
for (i=0;i<search_count;i++)
free(search_entries[i]);
free(search_entries);
search_entries=NULL;
search_count=0;
search_current=0;
}
scan_dir(".",stringof(hd),&search_entries,&search_count);
if (search_entries)
result=new_string(search_entries[0],strlen(search_entries[0]),"");
else
result=new_string("",0,"");
// name=dir(stringof(hd));
// if (name) result=new_string(name,strlen(name),"");
// else result=new_string("",0,"");
if (error) return;
moveresult(st,result);
}
void mdir0 (header *hd)
{
header *result;
if (search_entries) {
search_current++;
if (search_current<search_count)
result=new_string(search_entries[search_current],strlen(search_entries[search_current]),"");
if (error) return;
return;
}
result=new_string("",0,"");
}
void margs (header *hd)
/* return all args from realof(hd)-st argument on */
{ header *st=hd,*hd1,*result;
int i,n;
unsigned long size;
hd=getvalue(hd);
if (hd->type!=s_real) wrong_arg_in("args");
n=(int)*realof(hd);
if (n<1) wrong_arg_in("args");
if (n>actargn)
{ newram=(char *)st; return;
}
result=(header *)startlocal; i=1;
while (i<n && result<(header *)endlocal)
{ result=nextof(result); i++;
}
hd1=result;
while (i<actargn+1 && hd1<(header *)endlocal)
{ hd1=nextof(hd1); i++;
}
size=(char *)hd1-(char *)result;
if (size<=0)
{ output("Error in args!\n"); error=2021; return;
}
memmove((char *)st,(char *)result,size);
newram=(char *)st+size;
}
void margs0 (header *hd)
/* return all args from realof(hd)-st argument on */
{ header *st=(header *)newram,*hd1,*result;
int i,n;
unsigned long size;
n=actsp+1;
if (actsp==0) return;
if (n>actargn) n=actargn;
result=(header *)startlocal; i=1;
while (i<n && result<(header *)endlocal)
{ result=nextof(result); i++;
}
hd1=result;
while (i<actargn+1 && hd1<(header *)endlocal)
{ hd1=nextof(hd1); i++;
}
size=(char *)hd1-(char *)result;
if (size<=0)
{ output("Error in args!\n"); error=2021; return;
}
memmove((char *)st,(char *)result,size);
newram=(char *)st+size;
}
void mname (header *hd)
{ header *st=hd,*result;
hd=getvalue(hd); if (error) return;
result=new_string(hd->name,strlen(hd->name),"");
moveresult(st,result);
}
#ifdef WAVES
void mplaywav (header *hd)
{ header *st=hd;
hd=getvalue(hd); if (error) return;
if (hd->type!=s_string) wrong_arg_in("playwave");
sys_playwav(stringof(hd));
moveresult(st,hd);
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1