#define _ISOC99_SOURCE /* to get isfinite() */ #define _BSD_SOURCE /* to get __USE_MISC */ #include #include #include #include "list.h" #include "mapcalc.h" typedef double (*d_func)(void); typedef double (*d_func_d)(double d); typedef double (*d_func_dd)(double d0, double d1); typedef double (*d_func_di)(double d, int i); typedef double (*d_func_dai)(double d, int *i); typedef double (*d_func_p)(void *p0); typedef double (*d_func_pp)(void *p0, void *p1); typedef double (*d_func_ppp)(void *p0, void *p1, void *p2); typedef struct Numfunc { char *name; void *func; char *proto; }NUMFUNC; /* * Prototype Types: * - all return double or casted to double * "d" (double d) * "dd" (double d, double e) * "di" (double d, int i) * "dai" (double d, int *i) [a == asterisk] * * For no argument say NULL or "" */ static NUMFUNC nf[] = { { "acos", acos, "d" }, { "asin", asin, "d" }, { "atan", atan, "d" }, { "atan2", atan2, "dd" }, { "cos", cos, "d" }, { "sin", sin, "d" }, { "tan", tan, "d" }, { "cosh", cosh, "d" }, { "sinh", sinh, "d" }, { "tanh", tanh, "d" }, { "acosh", acosh, "d" }, { "asinh", asinh, "d" }, { "atanh", atanh, "d" }, { "exp", exp, "d" }, { "frexp", frexp, "dai" }, { "ldexp", ldexp, "di" }, { "ln", log, "d" }, { "log10", log10, "d" }, { "modf", modf, "dai" }, { "pow", pow, "dd" }, { "sqrt", sqrt, "d" }, { "hypot", hypot, "dd" }, { "cbrt", cbrt, "d" }, { "ceil", ceil, "d" }, { "fabs", fabs, "d" }, { "floor", floor, "d" }, { "fmod", fmod, "dd" }, { "drem", drem, "dd" }, { "j0", j0, "d" }, { "j1", j1, "d" }, { "jn", jn, "dd" }, { "y0", y0, "d" }, { "y1", y1, "d" }, { "yn", yn, "dd" }, { "erf", erf, "d" }, { "erfc", erfc, "d" }, { "lgamma", lgamma, "d" }, { "rint", rint, "d" }, { NULL, NULL, NULL } }; void init_num (void); void shownum (double d); void setnum (SYMBOL *var, double d); SYMBOL *mknumvar (SYMBOL *var, double d); double numfunc (SYMBOL *func, SYMBOL *arglist); double numop (int op, SYMBOL *opd1, SYMBOL *opd2); SYMBOL *mknum (double d); void init_num (void) { SYMBOL *sym; int i; for (i = 0; nf[i].name; i++) { sym = putsym (nf[i].name); sym->type = sym->itype = st_nfunc; sym->v.p = nf[i].func; sym->proto = nf[i].proto; sym->rettype = st_num; } /* add some handy constants */ sym = putsym ("e"); sym->type = sym->itype = st_num; sym->v.d = M_E; sym = putsym ("pi"); sym->type = sym->itype = st_num; sym->v.d = M_PI; } void shownum (double d) { if (!isfinite (d)) printf ("\t??.??\n"); else if (d == (int)d) printf ("\t%d\n", (int)d); else printf ("\t%g\n", d); } void setnum (SYMBOL *var, double d) { SYMBOL *sym; var->v.d = d; if (var->name) { sym = getsym (var->name); if (sym) sym->v.d = d; } shownum (d); freesym (var); } SYMBOL * mknumvar (SYMBOL *var, double d) { if (var) { var->name = var->v.p; var->type = var->itype = st_num; var->v.d = d; symtab = (SYMBOL *)listadd ((LIST *)symtab, (LIST *)var, cmpsymsym); } else { var = (SYMBOL *)listitem (sizeof (SYMBOL)); var->type = var->itype = st_num; var->v.d = d; } shownum (d); return var; } double numfunc (SYMBOL *func, SYMBOL *arglist) { double res = 0.0; int argc = -1; if (!func || !func->v.p || func->type != st_nfunc) { parseerror = 1; printf ("Can't call bad num-function\n"); } else argc = listcnt ((LIST *)arglist); if (argc == 0 && (!func->proto || !*func->proto)) res = (*(d_func)func->v.p)(); else if (argc == 1 && !strcmp (func->proto, "d")) res = (*(d_func_d)func->v.p)(arglist->v.d); else if (argc == 2 && !strcmp (func->proto, "dd")) res = (*(d_func_dd)func->v.p)(arglist->v.d, arglist->next->v.d); else if (argc == 2 && !strcmp (func->proto, "di")) res = (*(d_func_di)func->v.p)(arglist->v.d, (int)arglist->next->v.d); else if (argc == 3 && !strcmp (func->proto, "dai")) { int iptr; iptr = (int)arglist->next->v.d; res = (*(d_func_dai)func->v.p)(arglist->v.d, &iptr); arglist->next->v.d = (double)iptr; } else if (argc == 1 && !strcmp (func->proto, "p")) res = (*(d_func_p)func->v.p)(arglist->v.p); else if (argc == 2 && !strcmp (func->proto, "pp")) res = (*(d_func_pp)func->v.p)(arglist->v.p, arglist->next->v.p); else if (argc == 3 && !strcmp (func->proto, "ppp")) res = (*(d_func_ppp)func->v.p)(arglist->v.p, arglist->next->v.p, arglist->next->next->v.p); else { printf ("Bad arguments to numfunc %s\n", func->name); parseerror = 1; } listdelall ((LIST *)func, freesym); listdelall ((LIST *)arglist, freesym); return res; } double numop (int op, SYMBOL *opd1, SYMBOL *opd2) { SYMBOL *func, *arglist, *f; char buf[32]; double res = 0.0; if (opd1->itype == st_num) sprintf (buf, "num_op_func_%c", op); else if (opd1->itype == st_pnt) sprintf (buf, "pnt_op_func_%c", op); func = getsym (buf); if (!func) { if (opd1->itype == st_num) printf ("No function defined to perform ``number %c number''\n", op); else if (opd1->itype == st_pnt) printf ("No function defined to perform ``point %c point''\n", op); parseerror = 1; } else { f = (SYMBOL *)listitem (sizeof (SYMBOL)); symcpy (f, func); f->next = NULL; func = f; arglist = (SYMBOL *)listapp (NULL, (LIST *)opd1); arglist = (SYMBOL *)listapp ((LIST *)arglist, (LIST *)opd2); res = numfunc (func, arglist); } return res; } SYMBOL * mknum (double d) { SYMBOL *num; num = (SYMBOL *)listitem (sizeof (SYMBOL)); num->type = num->itype = st_num; num->v.d = d; return num; }