/* * The Spar Library - modular math parser * Copyright (C) 2000,2001 Davide Angelocola * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include sl_function sl_function_TABLE[] = { /* one arg functions... */ {"sin", "sin", /* name to invoke this function */ SL_FUNCTION_WITH_ONE_ARG, /* how many arguments it gets */ SL_FUNCTION_CLASS_TRIG, /* math type (for help command) */ sl_sin, /* function to call (one arg) */ (sl_function_tp) NULL /* function to call (two args) */ } , {"cos", "cos", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_TRIG, sl_cos, (sl_function_tp) NULL} , {"tan", "tan", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_TRIG, sl_tan, (sl_function_tp) NULL} , {"cotan", "cos(x) / sin(x)", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_TRIG, sl_cotan, (sl_function_tp) NULL} , {"asin", "arcsin", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_ITRIG, sl_arcsin, (sl_function_tp) NULL} , {"acos", "arccos", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_ITRIG, sl_arccos, (sl_function_tp) NULL} , {"atan", "arctan", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_ITRIG, sl_arctan, (sl_function_tp) NULL} , {"sinh", "sinh", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_HYPER, sl_sinh, (sl_function_tp) NULL} , {"cosh", "cosh", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_HYPER, sl_cosh, (sl_function_tp) NULL} , {"tanh", "tanh", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_HYPER, sl_tanh, (sl_function_tp) NULL} , {"asinh", "arcsinh", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_HYPER, sl_asinh, (sl_function_tp) NULL} , {"acosh", "arccosh", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_HYPER, sl_acosh, (sl_function_tp) NULL} , {"atanh", "arctanh", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_HYPER, sl_atanh, (sl_function_tp) NULL} , {"exp", "exp", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_EXP, sl_exp, (sl_function_tp) NULL} , {"expm1", "expm1", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_EXP, sl_expm1, (sl_function_tp) NULL} , {"log", "log", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_LOG, sl_log, (sl_function_tp) NULL} , {"log2", "log2", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_LOG, sl_log2, (sl_function_tp) NULL} , {"log10", "log10", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_LOG, sl_log10, (sl_function_tp) NULL} , {"log1p", "log1p", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_LOG, sl_log1p, (sl_function_tp) NULL} , {"floor", "floor", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_floor, (sl_function_tp) NULL} , {"ceil", "ceil", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_ceil, (sl_function_tp) NULL} , {"sgn", "sgn", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_sgn, (sl_function_tp) NULL} , {"abs", "abs", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_abs, (sl_function_tp) NULL} , {"deg", "deg", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_deg, (sl_function_tp) NULL} , {"rad", "rad", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_rad, (sl_function_tp) NULL} , {"fat", "!", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_fat, (sl_function_tp) NULL} , {"sum", "S", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_sum, (sl_function_tp) NULL} , {"inv", "inv", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_inv, (sl_function_tp) NULL} , {"max", "M", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_SPECIAL, (sl_function_p) NULL, sl_max} , {"min", "m", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_SPECIAL, (sl_function_p) NULL, sl_min} , {"sqrn", "x^(1/y)", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_EXP, (sl_function_p) NULL, sl_sqrn} , {"hypot", "hypot", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_ITRIG, (sl_function_p) NULL, sl_hypot} , {"mcd", "mcd", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_SPECIAL, (sl_function_p) NULL, sl_mcd} , {"atan2", "arctan(y/x)", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_ITRIG, (sl_function_p) NULL, sl_atan2} , {"expn", "expn", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_EXP, (sl_function_p) NULL, sl_expn} , /* * Function 'pow' and 'mod' removed * replaced with the parser operators: * '^' for pow * '%' for mod * * uncomment if you want to call this operator also as function */ /* {"pow", "pow", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_EXP, (sl_function_p) NULL, sl_pow} , {"mod", "rem", SL_FUNCTION_WITH_TWO_ARG, SL_FUNCTION_CLASS_SPECIAL, (sl_function_p) NULL, sl_mod} , */ {"isnan", "isnan", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_isnan, (sl_function_tp) NULL} , {"isinf", "isinf", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_isinf, (sl_function_tp) NULL} , {"isfinite", "finite", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_finite, (sl_function_tp) NULL} , {"fib", "fibonacci", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_SPECIAL, sl_fib, (sl_function_tp) NULL} , {"pow2", "2^x", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_EXP, sl_pow2, (sl_function_tp) NULL} , {"sqrt", "square root", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_EXP, sl_sqrt, (sl_function_tp) NULL} , {"cbrt", "cube root", SL_FUNCTION_WITH_ONE_ARG, SL_FUNCTION_CLASS_EXP, sl_cbrt, (sl_function_tp) NULL} , }; const char *sl_function_type_TABLE[SL_FUNCTION_CLASS_COUNTER] = { "Trigonometric", "Inverse Trigonometric", "Exponential", "Logarithm", "Hyperbolic", "Special", "User_defined" }; const char *sl_function_args_TABLE[SL_FUNCTION_WITH_COUNTER] = { "()", "(x)", "(x,y)", "(...)" }; const int SL_FUNCTION_TABLE_LENGTH = sizeof (sl_function_TABLE) / sizeof (sl_function_TABLE[0]); int __function_cmp (const sl_function * f1, const sl_function * f2) { return strncmp (f1->name, f2->name, SL_IDENTIFIER_LENGHT); } int sl_function_init (void) { return sl_qsort (sl_function_TABLE, SL_FUNCTION_TABLE_LENGTH, sizeof (sl_function), (int (*)(const void *, const void *)) __function_cmp); } int sl_function_check (const char *name) { sl_function *r; r = sl_bsearch (name, sl_function_TABLE, SL_FUNCTION_TABLE_LENGTH, sizeof (sl_function), (int (*)(const void *, const void *)) __function_cmp); if (r) return ((int) r - (int) sl_function_TABLE) / sizeof (sl_function); else return SL_SYMBOL_NOT_FOUND; } void sl_function_print_all (void) { sl_table_column function_cols[] = { {"Name", SL_IDENTIFIER_LENGHT}, {"Arg", 4}, {"Math Form", SL_MESSAGE_LENGHT}, {{0}} }; sl_table_create ("Functions", function_cols, SL_FUNCTION_TABLE_LENGTH, sl_table_print_function); } int sl_function_make_help (const char *name, sl_function_help * tmp) { int fnc_code = sl_function_check (name); if (fnc_code != SL_SYMBOL_NOT_FOUND) { strcat (strcpy (tmp->math, sl_function_TABLE[fnc_code].math), sl_function_args_TABLE[sl_function_TABLE[fnc_code].args]); strcat (strcpy (tmp->type, sl_function_type_TABLE[sl_function_TABLE[fnc_code].type]), " function"); strcpy (tmp->name, sl_function_TABLE[fnc_code].name); tmp->args = sl_function_TABLE[fnc_code].args; return 1; } return 0; } double sl_function_run (const char *name, double argv[]) { sl_function *r; r = sl_bsearch ((const void *) name, sl_function_TABLE, SL_FUNCTION_TABLE_LENGTH, sizeof (sl_function), (int (*)(const void *, const void *)) __function_cmp); switch (r->args) { case SL_FUNCTION_WITH_ONE_ARG: return r->func (argv[0]); break; case SL_FUNCTION_WITH_TWO_ARG: return r->func2 (argv[0], argv[1]); break; case SL_FUNCTION_WITH_VAR_ARG: case SL_FUNCTION_WITH_COUNTER: break; } return 0.0; } sl_function_args_t sl_function_get_argc (int code) { return sl_function_TABLE[code].args; } const char * sl_function_get_name (int code) { return sl_function_TABLE[code].name; }