xref: /aosp_15_r20/external/angle/src/third_party/ceval/ceval.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker #ifndef CEVAL
2*8975f5c5SAndroid Build Coastguard Worker #define CEVAL
3*8975f5c5SAndroid Build Coastguard Worker //functions accessible from main()
4*8975f5c5SAndroid Build Coastguard Worker // - double ceval_result(char * inp) returns the result of valid math expression stored as a char array `inp`
5*8975f5c5SAndroid Build Coastguard Worker // - void ceval_tree(char * inp) prints the parse tree for the input expression `inp`
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker #include<stdio.h>
8*8975f5c5SAndroid Build Coastguard Worker #include<string.h>
9*8975f5c5SAndroid Build Coastguard Worker #include<math.h>
10*8975f5c5SAndroid Build Coastguard Worker #include<ctype.h>
11*8975f5c5SAndroid Build Coastguard Worker #include<stdarg.h>
12*8975f5c5SAndroid Build Coastguard Worker /****************************************** TOKENS ***********************************************/
13*8975f5c5SAndroid Build Coastguard Worker typedef enum ceval_node_id {
14*8975f5c5SAndroid Build Coastguard Worker     CEVAL_WHITESPACE, CEVAL_OPENPAR, CEVAL_CLOSEPAR, CEVAL_COMMA,
15*8975f5c5SAndroid Build Coastguard Worker     CEVAL_OR, CEVAL_AND, CEVAL_BIT_OR, CEVAL_BIT_XOR,
16*8975f5c5SAndroid Build Coastguard Worker     CEVAL_BIT_AND, CEVAL_EQUAL, CEVAL_NOTEQUAL,CEVAL_LESSER,
17*8975f5c5SAndroid Build Coastguard Worker     CEVAL_GREATER, CEVAL_LESSER_S, CEVAL_GREATER_S, CEVAL_BIT_LSHIFT,
18*8975f5c5SAndroid Build Coastguard Worker     CEVAL_BIT_RSHIFT, CEVAL_PLUS, CEVAL_MINUS, CEVAL_TIMES,
19*8975f5c5SAndroid Build Coastguard Worker     CEVAL_DIVIDE, CEVAL_MODULO, CEVAL_QUOTIENT, CEVAL_POW,
20*8975f5c5SAndroid Build Coastguard Worker     CEVAL_GCD, CEVAL_HCF, CEVAL_LCM, CEVAL_LOG,
21*8975f5c5SAndroid Build Coastguard Worker     CEVAL_ATAN2, CEVAL_SCI2DEC, CEVAL_POWFUN,
22*8975f5c5SAndroid Build Coastguard Worker 
23*8975f5c5SAndroid Build Coastguard Worker     CEVAL_ABS, CEVAL_EXP, CEVAL_SQRT,CEVAL_CBRT,
24*8975f5c5SAndroid Build Coastguard Worker     CEVAL_LN, CEVAL_LOG10, CEVAL_CEIL, CEVAL_FLOOR,
25*8975f5c5SAndroid Build Coastguard Worker     CEVAL_SIGNUM, CEVAL_FACTORIAL, CEVAL_INT, CEVAL_FRAC,
26*8975f5c5SAndroid Build Coastguard Worker     CEVAL_DEG2RAD, CEVAL_RAD2DEG, CEVAL_SIN, CEVAL_COS,
27*8975f5c5SAndroid Build Coastguard Worker     CEVAL_TAN, CEVAL_ASIN, CEVAL_ACOS, CEVAL_ATAN,
28*8975f5c5SAndroid Build Coastguard Worker     CEVAL_SINH, CEVAL_COSH, CEVAL_TANH,CEVAL_NOT,
29*8975f5c5SAndroid Build Coastguard Worker     CEVAL_BIT_NOT,CEVAL_POSSIGN, CEVAL_NEGSIGN,
30*8975f5c5SAndroid Build Coastguard Worker 
31*8975f5c5SAndroid Build Coastguard Worker     CEVAL_NUMBER, CEVAL_CONST_PI, CEVAL_CONST_E
32*8975f5c5SAndroid Build Coastguard Worker } ceval_node_id;
33*8975f5c5SAndroid Build Coastguard Worker typedef enum ceval_token_prec_specifiers {
34*8975f5c5SAndroid Build Coastguard Worker // precedences :: <https://en.cppreference.com/w/cpp/language/operator_precedence>
35*8975f5c5SAndroid Build Coastguard Worker // these precision specifiers are ordered in the ascending order of their precedences
36*8975f5c5SAndroid Build Coastguard Worker // here, the higher precedence operators are evaluated first and end up at the bottom of the parse trees
37*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_IGNORE,
38*8975f5c5SAndroid Build Coastguard Worker     // {' ', '\t', '\n', '\b', '\r'}
39*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_PARANTHESES,
40*8975f5c5SAndroid Build Coastguard Worker     // {'(', ')'}
41*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_COMMA_OPR,
42*8975f5c5SAndroid Build Coastguard Worker     // {','}
43*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_LOGICAL_OR_OPR,
44*8975f5c5SAndroid Build Coastguard Worker     // {'||'}
45*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_LOGICAL_AND_OPR,
46*8975f5c5SAndroid Build Coastguard Worker     // {'&&'}
47*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_BIT_OR_OPR,
48*8975f5c5SAndroid Build Coastguard Worker     // {'|'}
49*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_BIT_XOR_OPR,
50*8975f5c5SAndroid Build Coastguard Worker     // {'^'}
51*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_BIT_AND_OPR,
52*8975f5c5SAndroid Build Coastguard Worker     // {'&'}
53*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_EQUALITY_OPRS,
54*8975f5c5SAndroid Build Coastguard Worker     // {'==', '!='}
55*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_RELATIONAL_OPRS,
56*8975f5c5SAndroid Build Coastguard Worker     // {'<', '>', '<=', '>='}
57*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_BIT_SHIFT_OPRS,
58*8975f5c5SAndroid Build Coastguard Worker     // {'<<', '>>'}
59*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_ADDITIVE_OPRS,
60*8975f5c5SAndroid Build Coastguard Worker     // {'+', '-'}
61*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_SIGN_OPRS,
62*8975f5c5SAndroid Build Coastguard Worker     // {'+', '-'}
63*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_MULTIPLICATIVE_OPRS,
64*8975f5c5SAndroid Build Coastguard Worker     // {'*', '/', '%', '//'}
65*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_EXPONENTIATION_OPR,
66*8975f5c5SAndroid Build Coastguard Worker     // {'**'}
67*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_FUNCTIONS,
68*8975f5c5SAndroid Build Coastguard Worker     // {
69*8975f5c5SAndroid Build Coastguard Worker     //     'exp()', 'sqrt()', 'cbrt()', 'sin()',
70*8975f5c5SAndroid Build Coastguard Worker     //     'cos()', 'tan()', 'asin()', 'acos()',
71*8975f5c5SAndroid Build Coastguard Worker     //     'atan()', 'sinh()', 'cosh()', 'tanh()',
72*8975f5c5SAndroid Build Coastguard Worker     //     'abs()', 'ceil()', 'floor()', 'log10()',
73*8975f5c5SAndroid Build Coastguard Worker     //     'ln()', 'deg2rad()', 'rad2deg()', 'signum()',
74*8975f5c5SAndroid Build Coastguard Worker     //     'int()', 'frac()', 'fact()', `pow()`,
75*8975f5c5SAndroid Build Coastguard Worker     //     `atan2()`, `gcd()`, `hcf()`, `lcm()`,
76*8975f5c5SAndroid Build Coastguard Worker     //     `log()`
77*8975f5c5SAndroid Build Coastguard Worker     // }
78*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_NOT_OPRS,
79*8975f5c5SAndroid Build Coastguard Worker     // {'!', '~'}}
80*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_SCI2DEC_OPR,
81*8975f5c5SAndroid Build Coastguard Worker     // {'e'},
82*8975f5c5SAndroid Build Coastguard Worker     CEVAL_PREC_NUMERIC
83*8975f5c5SAndroid Build Coastguard Worker     // {'_pi', '_e', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
84*8975f5c5SAndroid Build Coastguard Worker } ceval_token_prec_specifiers;
85*8975f5c5SAndroid Build Coastguard Worker typedef enum ceval_token_type {
86*8975f5c5SAndroid Build Coastguard Worker     CEVAL_UNARY_OPERATOR,
87*8975f5c5SAndroid Build Coastguard Worker     CEVAL_BINARY_OPERATOR,
88*8975f5c5SAndroid Build Coastguard Worker     CEVAL_UNARY_FUNCTION,
89*8975f5c5SAndroid Build Coastguard Worker     CEVAL_BINARY_FUNCTION,
90*8975f5c5SAndroid Build Coastguard Worker     CEVAL_OTHER
91*8975f5c5SAndroid Build Coastguard Worker } ceval_token_type;
92*8975f5c5SAndroid Build Coastguard Worker typedef struct ceval_token_info_ {
93*8975f5c5SAndroid Build Coastguard Worker     ceval_node_id id;
94*8975f5c5SAndroid Build Coastguard Worker     const char * symbol;
95*8975f5c5SAndroid Build Coastguard Worker     double prec;
96*8975f5c5SAndroid Build Coastguard Worker     ceval_token_type token_type;
97*8975f5c5SAndroid Build Coastguard Worker } ceval_token_info_;
98*8975f5c5SAndroid Build Coastguard Worker ceval_token_info_ ceval_token_info[] = {
99*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_WHITESPACE, " ", CEVAL_PREC_IGNORE, CEVAL_OTHER },
100*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_WHITESPACE, "\n", CEVAL_PREC_IGNORE, CEVAL_OTHER },
101*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_WHITESPACE, "\t", CEVAL_PREC_IGNORE, CEVAL_OTHER },
102*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_WHITESPACE, "\r", CEVAL_PREC_IGNORE, CEVAL_OTHER },
103*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_WHITESPACE, "\b", CEVAL_PREC_IGNORE, CEVAL_OTHER },
104*8975f5c5SAndroid Build Coastguard Worker 
105*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_DEG2RAD, "deg2rad", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
106*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_RAD2DEG, "rad2deg", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
107*8975f5c5SAndroid Build Coastguard Worker 
108*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_SIGNUM, "signum", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
109*8975f5c5SAndroid Build Coastguard Worker 
110*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_ATAN2, "atan2", CEVAL_PREC_FUNCTIONS, CEVAL_BINARY_FUNCTION },
111*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_LOG10, "log10", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
112*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_FLOOR, "floor", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
113*8975f5c5SAndroid Build Coastguard Worker 
114*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_SQRT, "sqrt", CEVAL_PREC_FUNCTIONS , CEVAL_UNARY_FUNCTION },
115*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_CBRT, "cbrt", CEVAL_PREC_FUNCTIONS , CEVAL_UNARY_FUNCTION },
116*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_CEIL, "ceil", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
117*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_FRAC, "frac", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
118*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_FACTORIAL, "fact", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
119*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_SINH, "sinh", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
120*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_COSH, "cosh", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
121*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_TANH, "tanh", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
122*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_ASIN, "asin", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
123*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_ACOS, "acos", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
124*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_ATAN, "atan", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
125*8975f5c5SAndroid Build Coastguard Worker 
126*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_POWFUN, "pow", CEVAL_PREC_FUNCTIONS, CEVAL_BINARY_FUNCTION },
127*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_GCD, "gcd", CEVAL_PREC_FUNCTIONS, CEVAL_BINARY_FUNCTION },
128*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_HCF, "hcf", CEVAL_PREC_FUNCTIONS, CEVAL_BINARY_FUNCTION },
129*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_LCM, "lcm", CEVAL_PREC_FUNCTIONS, CEVAL_BINARY_FUNCTION },
130*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_LOG, "log", CEVAL_PREC_FUNCTIONS, CEVAL_BINARY_FUNCTION },
131*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_INT, "int", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
132*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_SIN, "sin", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
133*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_COS, "cos", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
134*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_TAN, "tan", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
135*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_ABS, "abs", CEVAL_PREC_FUNCTIONS , CEVAL_UNARY_FUNCTION },
136*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_EXP, "exp", CEVAL_PREC_FUNCTIONS , CEVAL_UNARY_FUNCTION },
137*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_CONST_PI, "_pi", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
138*8975f5c5SAndroid Build Coastguard Worker 
139*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_CONST_E, "_e", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
140*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_LN, "ln", CEVAL_PREC_FUNCTIONS, CEVAL_UNARY_FUNCTION },
141*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_OR, "||", CEVAL_PREC_LOGICAL_OR_OPR, CEVAL_BINARY_OPERATOR },
142*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_AND, "&&", CEVAL_PREC_LOGICAL_AND_OPR, CEVAL_BINARY_OPERATOR },
143*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_EQUAL, "==", CEVAL_PREC_EQUALITY_OPRS, CEVAL_BINARY_OPERATOR },
144*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NOTEQUAL, "!=", CEVAL_PREC_EQUALITY_OPRS, CEVAL_BINARY_OPERATOR },
145*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_LESSER, "<=", CEVAL_PREC_RELATIONAL_OPRS , CEVAL_BINARY_OPERATOR },
146*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_GREATER, ">=", CEVAL_PREC_RELATIONAL_OPRS , CEVAL_BINARY_OPERATOR },
147*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_BIT_LSHIFT, "<<", CEVAL_PREC_BIT_SHIFT_OPRS, CEVAL_BINARY_OPERATOR},
148*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_BIT_RSHIFT, ">>", CEVAL_PREC_BIT_SHIFT_OPRS, CEVAL_BINARY_OPERATOR},
149*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_QUOTIENT, "//", CEVAL_PREC_MULTIPLICATIVE_OPRS , CEVAL_BINARY_OPERATOR },
150*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_POW, "**", CEVAL_PREC_EXPONENTIATION_OPR , CEVAL_BINARY_OPERATOR },
151*8975f5c5SAndroid Build Coastguard Worker 
152*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_OPENPAR, "(", CEVAL_PREC_PARANTHESES, CEVAL_OTHER },
153*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_CLOSEPAR, ")", CEVAL_PREC_PARANTHESES, CEVAL_OTHER },
154*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_COMMA, ",", CEVAL_PREC_COMMA_OPR , CEVAL_BINARY_OPERATOR },
155*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_BIT_OR, "|", CEVAL_PREC_BIT_OR_OPR, CEVAL_BINARY_OPERATOR},
156*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_BIT_XOR, "^", CEVAL_PREC_BIT_XOR_OPR, CEVAL_BINARY_OPERATOR},
157*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_BIT_AND, "&", CEVAL_PREC_BIT_AND_OPR, CEVAL_BINARY_OPERATOR},
158*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_LESSER_S, "<", CEVAL_PREC_RELATIONAL_OPRS , CEVAL_BINARY_OPERATOR },
159*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_GREATER_S, ">", CEVAL_PREC_RELATIONAL_OPRS , CEVAL_BINARY_OPERATOR },
160*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_PLUS, "+", CEVAL_PREC_ADDITIVE_OPRS , CEVAL_BINARY_OPERATOR },
161*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_MINUS, "-", CEVAL_PREC_ADDITIVE_OPRS , CEVAL_BINARY_OPERATOR },
162*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_POSSIGN, "+", CEVAL_PREC_SIGN_OPRS, CEVAL_UNARY_OPERATOR },
163*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NEGSIGN, "-", CEVAL_PREC_SIGN_OPRS, CEVAL_UNARY_OPERATOR },
164*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_TIMES, "*", CEVAL_PREC_MULTIPLICATIVE_OPRS , CEVAL_BINARY_OPERATOR },
165*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_DIVIDE, "/", CEVAL_PREC_MULTIPLICATIVE_OPRS , CEVAL_BINARY_OPERATOR },
166*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_MODULO, "%", CEVAL_PREC_MULTIPLICATIVE_OPRS , CEVAL_BINARY_OPERATOR },
167*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NOT, "!", CEVAL_PREC_NOT_OPRS, CEVAL_UNARY_FUNCTION},
168*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_BIT_NOT, "~", CEVAL_PREC_NOT_OPRS, CEVAL_UNARY_OPERATOR},
169*8975f5c5SAndroid Build Coastguard Worker 
170*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_SCI2DEC, "e", CEVAL_PREC_SCI2DEC_OPR , CEVAL_BINARY_OPERATOR },
171*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "0", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
172*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "1", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
173*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "2", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
174*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "3", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
175*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "4", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
176*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "5", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
177*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "6", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
178*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "7", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
179*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "8", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
180*8975f5c5SAndroid Build Coastguard Worker     { CEVAL_NUMBER, "9", CEVAL_PREC_NUMERIC, CEVAL_OTHER },
181*8975f5c5SAndroid Build Coastguard Worker };
182*8975f5c5SAndroid Build Coastguard Worker #ifndef CEVAL_TOKEN_TABLE_SIZE
183*8975f5c5SAndroid Build Coastguard Worker #define CEVAL_TOKEN_TABLE_SIZE sizeof(ceval_token_info) / sizeof(ceval_token_info[0])
184*8975f5c5SAndroid Build Coastguard Worker #endif
ceval_is_binary_opr(ceval_node_id id)185*8975f5c5SAndroid Build Coastguard Worker int ceval_is_binary_opr(ceval_node_id id) {
186*8975f5c5SAndroid Build Coastguard Worker     for(unsigned int i = 0; i < CEVAL_TOKEN_TABLE_SIZE; i++) {
187*8975f5c5SAndroid Build Coastguard Worker         if (ceval_token_info[i].id == id && ceval_token_info[i].token_type == CEVAL_BINARY_OPERATOR) {
188*8975f5c5SAndroid Build Coastguard Worker             return 1;
189*8975f5c5SAndroid Build Coastguard Worker         }
190*8975f5c5SAndroid Build Coastguard Worker     }
191*8975f5c5SAndroid Build Coastguard Worker     return 0;
192*8975f5c5SAndroid Build Coastguard Worker }
ceval_is_binary_fun(ceval_node_id id)193*8975f5c5SAndroid Build Coastguard Worker int ceval_is_binary_fun(ceval_node_id id) {
194*8975f5c5SAndroid Build Coastguard Worker     for(unsigned int i = 0; i < CEVAL_TOKEN_TABLE_SIZE; i++) {
195*8975f5c5SAndroid Build Coastguard Worker         if (ceval_token_info[i].id == id && ceval_token_info[i].token_type == CEVAL_BINARY_FUNCTION) {
196*8975f5c5SAndroid Build Coastguard Worker             return 1;
197*8975f5c5SAndroid Build Coastguard Worker         }
198*8975f5c5SAndroid Build Coastguard Worker     }
199*8975f5c5SAndroid Build Coastguard Worker     return 0;
200*8975f5c5SAndroid Build Coastguard Worker }
ceval_token_symbol(ceval_node_id id)201*8975f5c5SAndroid Build Coastguard Worker const char * ceval_token_symbol(ceval_node_id id) {
202*8975f5c5SAndroid Build Coastguard Worker     for(unsigned int i = 0; i < CEVAL_TOKEN_TABLE_SIZE; i++) {
203*8975f5c5SAndroid Build Coastguard Worker         if (id == ceval_token_info[i].id) {
204*8975f5c5SAndroid Build Coastguard Worker             return ceval_token_info[i].symbol;
205*8975f5c5SAndroid Build Coastguard Worker         }
206*8975f5c5SAndroid Build Coastguard Worker     }
207*8975f5c5SAndroid Build Coastguard Worker return "";
208*8975f5c5SAndroid Build Coastguard Worker }
ceval_token_id(char * symbol)209*8975f5c5SAndroid Build Coastguard Worker ceval_node_id ceval_token_id(char * symbol) {
210*8975f5c5SAndroid Build Coastguard Worker     for(unsigned int i = 0; i < CEVAL_TOKEN_TABLE_SIZE; i++) {
211*8975f5c5SAndroid Build Coastguard Worker         if (!strcmp(ceval_token_info[i].symbol, symbol)) {
212*8975f5c5SAndroid Build Coastguard Worker             return ceval_token_info[i].id;
213*8975f5c5SAndroid Build Coastguard Worker         }
214*8975f5c5SAndroid Build Coastguard Worker     }
215*8975f5c5SAndroid Build Coastguard Worker return CEVAL_WHITESPACE;
216*8975f5c5SAndroid Build Coastguard Worker }
ceval_token_prec(ceval_node_id id)217*8975f5c5SAndroid Build Coastguard Worker double ceval_token_prec(ceval_node_id id) {
218*8975f5c5SAndroid Build Coastguard Worker     for(unsigned int i = 0; i < CEVAL_TOKEN_TABLE_SIZE; i++) {
219*8975f5c5SAndroid Build Coastguard Worker         if (id == ceval_token_info[i].id) {
220*8975f5c5SAndroid Build Coastguard Worker             return ceval_token_info[i].prec;
221*8975f5c5SAndroid Build Coastguard Worker         }
222*8975f5c5SAndroid Build Coastguard Worker     }
223*8975f5c5SAndroid Build Coastguard Worker return 0;
224*8975f5c5SAndroid Build Coastguard Worker }
225*8975f5c5SAndroid Build Coastguard Worker typedef struct ceval_node {
226*8975f5c5SAndroid Build Coastguard Worker     enum ceval_node_id id;
227*8975f5c5SAndroid Build Coastguard Worker     double pre;
228*8975f5c5SAndroid Build Coastguard Worker     double number;
229*8975f5c5SAndroid Build Coastguard Worker     struct ceval_node * left, * right, * parent;
230*8975f5c5SAndroid Build Coastguard Worker }
231*8975f5c5SAndroid Build Coastguard Worker ceval_node;
232*8975f5c5SAndroid Build Coastguard Worker #ifdef __cplusplus
233*8975f5c5SAndroid Build Coastguard Worker   #define CEVAL_CXX
234*8975f5c5SAndroid Build Coastguard Worker   #include<iostream>
235*8975f5c5SAndroid Build Coastguard Worker   #include<string>
236*8975f5c5SAndroid Build Coastguard Worker #endif
237*8975f5c5SAndroid Build Coastguard Worker /***************************************** !TOKENS *******************************************/
238*8975f5c5SAndroid Build Coastguard Worker 
239*8975f5c5SAndroid Build Coastguard Worker /****************************************** FUNCTIONS ******************************************/
240*8975f5c5SAndroid Build Coastguard Worker //constant definitions
241*8975f5c5SAndroid Build Coastguard Worker #ifdef M_PI
242*8975f5c5SAndroid Build Coastguard Worker #define CEVAL_PI M_PI
243*8975f5c5SAndroid Build Coastguard Worker #else
244*8975f5c5SAndroid Build Coastguard Worker #define CEVAL_PI 3.14159265358979323846
245*8975f5c5SAndroid Build Coastguard Worker #endif
246*8975f5c5SAndroid Build Coastguard Worker #ifdef M_E
247*8975f5c5SAndroid Build Coastguard Worker #define CEVAL_E M_E
248*8975f5c5SAndroid Build Coastguard Worker #else
249*8975f5c5SAndroid Build Coastguard Worker #define CEVAL_E 2.71828182845904523536
250*8975f5c5SAndroid Build Coastguard Worker #endif
251*8975f5c5SAndroid Build Coastguard Worker 
252*8975f5c5SAndroid Build Coastguard Worker #ifndef CEVAL_EPSILON
253*8975f5c5SAndroid Build Coastguard Worker #define CEVAL_EPSILON 1e-2
254*8975f5c5SAndroid Build Coastguard Worker #endif
255*8975f5c5SAndroid Build Coastguard Worker #ifndef CEVAL_DELTA
256*8975f5c5SAndroid Build Coastguard Worker #define CEVAL_DELTA 1e-6
257*8975f5c5SAndroid Build Coastguard Worker #endif
258*8975f5c5SAndroid Build Coastguard Worker #ifndef CEVAL_MAX_DIGITS
259*8975f5c5SAndroid Build Coastguard Worker #define CEVAL_MAX_DIGITS 15
260*8975f5c5SAndroid Build Coastguard Worker #endif
261*8975f5c5SAndroid Build Coastguard Worker //these can be defined by the user before the include directive depending the desired level of precision
262*8975f5c5SAndroid Build Coastguard Worker 
263*8975f5c5SAndroid Build Coastguard Worker //helper function prototypes
264*8975f5c5SAndroid Build Coastguard Worker void ceval_error(const char * , ...);
265*8975f5c5SAndroid Build Coastguard Worker double ceval_gcd_binary(int, int);
266*8975f5c5SAndroid Build Coastguard Worker char * ceval_shrink(char * );
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker //single argument funtion prototypes
269*8975f5c5SAndroid Build Coastguard Worker double ceval_signum(double);
270*8975f5c5SAndroid Build Coastguard Worker double ceval_asin(double);
271*8975f5c5SAndroid Build Coastguard Worker double ceval_acos(double);
272*8975f5c5SAndroid Build Coastguard Worker double ceval_atan(double);
273*8975f5c5SAndroid Build Coastguard Worker double ceval_sin(double);
274*8975f5c5SAndroid Build Coastguard Worker double ceval_cos(double);
275*8975f5c5SAndroid Build Coastguard Worker double ceval_tan(double);
276*8975f5c5SAndroid Build Coastguard Worker double ceval_sinh(double);
277*8975f5c5SAndroid Build Coastguard Worker double ceval_cosh(double);
278*8975f5c5SAndroid Build Coastguard Worker double ceval_tanh(double);
279*8975f5c5SAndroid Build Coastguard Worker double ceval_rad2deg(double);
280*8975f5c5SAndroid Build Coastguard Worker double ceval_deg2rad(double);
281*8975f5c5SAndroid Build Coastguard Worker double ceval_int_part(double);
282*8975f5c5SAndroid Build Coastguard Worker double ceval_frac_part(double);
283*8975f5c5SAndroid Build Coastguard Worker double ceval_log10(double);
284*8975f5c5SAndroid Build Coastguard Worker double ceval_ln(double);
285*8975f5c5SAndroid Build Coastguard Worker double ceval_exp(double);
286*8975f5c5SAndroid Build Coastguard Worker double ceval_factorial(double);
287*8975f5c5SAndroid Build Coastguard Worker double ceval_positive_sign(double);
288*8975f5c5SAndroid Build Coastguard Worker double ceval_negative_sign(double);
289*8975f5c5SAndroid Build Coastguard Worker double ceval_abs(double);
290*8975f5c5SAndroid Build Coastguard Worker double ceval_sqrt(double);
291*8975f5c5SAndroid Build Coastguard Worker double ceval_sqrt(double);
292*8975f5c5SAndroid Build Coastguard Worker double ceval_cbrt(double);
293*8975f5c5SAndroid Build Coastguard Worker double ceval_ceil(double);
294*8975f5c5SAndroid Build Coastguard Worker double ceval_floor(double);
295*8975f5c5SAndroid Build Coastguard Worker double ceval_not(double);
296*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_not(double);
297*8975f5c5SAndroid Build Coastguard Worker 
298*8975f5c5SAndroid Build Coastguard Worker //double argument function prototypes
299*8975f5c5SAndroid Build Coastguard Worker double ceval_sum(double, double, int);
300*8975f5c5SAndroid Build Coastguard Worker double ceval_diff(double, double, int);
301*8975f5c5SAndroid Build Coastguard Worker double ceval_prod(double, double, int);
302*8975f5c5SAndroid Build Coastguard Worker double ceval_div(double, double, int);
303*8975f5c5SAndroid Build Coastguard Worker double ceval_quotient(double, double, int);
304*8975f5c5SAndroid Build Coastguard Worker double ceval_modulus(double, double, int);
305*8975f5c5SAndroid Build Coastguard Worker double ceval_gcd(double, double, int);
306*8975f5c5SAndroid Build Coastguard Worker double ceval_hcf(double, double, int);
307*8975f5c5SAndroid Build Coastguard Worker double ceval_lcm(double, double, int);
308*8975f5c5SAndroid Build Coastguard Worker double ceval_log(double, double, int);
309*8975f5c5SAndroid Build Coastguard Worker double ceval_are_equal(double, double, int);
310*8975f5c5SAndroid Build Coastguard Worker double ceval_not_equal(double, double, int);
311*8975f5c5SAndroid Build Coastguard Worker double ceval_lesser(double, double, int);
312*8975f5c5SAndroid Build Coastguard Worker double ceval_greater(double, double, int);
313*8975f5c5SAndroid Build Coastguard Worker double ceval_lesser_s(double, double, int);
314*8975f5c5SAndroid Build Coastguard Worker double ceval_greater_s(double, double, int);
315*8975f5c5SAndroid Build Coastguard Worker double ceval_comma(double, double, int);
316*8975f5c5SAndroid Build Coastguard Worker double ceval_power(double, double, int);
317*8975f5c5SAndroid Build Coastguard Worker double ceval_atan2(double, double, int);
318*8975f5c5SAndroid Build Coastguard Worker double ceval_sci2dec(double, double, int);
319*8975f5c5SAndroid Build Coastguard Worker double ceval_and(double, double, int);
320*8975f5c5SAndroid Build Coastguard Worker double ceval_or(double, double, int);
321*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_and(double, double, int);
322*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_xor(double, double, int);
323*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_or(double, double, int);
324*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_lshift(double, double, int);
325*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_rshift(double, double, int);
326*8975f5c5SAndroid Build Coastguard Worker 
327*8975f5c5SAndroid Build Coastguard Worker //helper function definitions
ceval_error(const char * error_format_string,...)328*8975f5c5SAndroid Build Coastguard Worker void ceval_error(const char* error_format_string, ...) {
329*8975f5c5SAndroid Build Coastguard Worker     #ifndef CEVAL_STOICAL
330*8975f5c5SAndroid Build Coastguard Worker         // start whining
331*8975f5c5SAndroid Build Coastguard Worker         printf("\n[ceval]: ");
332*8975f5c5SAndroid Build Coastguard Worker         va_list args;
333*8975f5c5SAndroid Build Coastguard Worker         va_start(args, error_format_string);
334*8975f5c5SAndroid Build Coastguard Worker         vprintf(error_format_string, args);
335*8975f5c5SAndroid Build Coastguard Worker         va_end(args);
336*8975f5c5SAndroid Build Coastguard Worker         printf("\n");
337*8975f5c5SAndroid Build Coastguard Worker     #endif
338*8975f5c5SAndroid Build Coastguard Worker }
ceval_gcd_binary(int a,int b)339*8975f5c5SAndroid Build Coastguard Worker double ceval_gcd_binary(int a, int b) {
340*8975f5c5SAndroid Build Coastguard Worker     if (a == 0 && b == 0)
341*8975f5c5SAndroid Build Coastguard Worker         return 0;
342*8975f5c5SAndroid Build Coastguard Worker     while (b) {
343*8975f5c5SAndroid Build Coastguard Worker         a %= b;
344*8975f5c5SAndroid Build Coastguard Worker         b ^= a;
345*8975f5c5SAndroid Build Coastguard Worker         a ^= b;
346*8975f5c5SAndroid Build Coastguard Worker         b ^= a;
347*8975f5c5SAndroid Build Coastguard Worker     }
348*8975f5c5SAndroid Build Coastguard Worker     return a;
349*8975f5c5SAndroid Build Coastguard Worker }
ceval_shrink(char * x)350*8975f5c5SAndroid Build Coastguard Worker char * ceval_shrink(char * x) {
351*8975f5c5SAndroid Build Coastguard Worker     char * y = x;
352*8975f5c5SAndroid Build Coastguard Worker     unsigned int len = 0;
353*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < strlen(x); i++) {
354*8975f5c5SAndroid Build Coastguard Worker         if(x[i] == ' ' || x[i] == '\n' || x[i] == '\t' || x[i] == '\r') {
355*8975f5c5SAndroid Build Coastguard Worker             continue;
356*8975f5c5SAndroid Build Coastguard Worker         } else {
357*8975f5c5SAndroid Build Coastguard Worker             if(x[i]=='(' && x[i+1]==')') {
358*8975f5c5SAndroid Build Coastguard Worker                 // empty pairs of parantheses are ignored
359*8975f5c5SAndroid Build Coastguard Worker                 // simlar to c lang where {} are ignored as empty blocks of code
360*8975f5c5SAndroid Build Coastguard Worker                 i++;
361*8975f5c5SAndroid Build Coastguard Worker                 continue;
362*8975f5c5SAndroid Build Coastguard Worker             }
363*8975f5c5SAndroid Build Coastguard Worker             *(y + len) = (char)tolower(x[i]);
364*8975f5c5SAndroid Build Coastguard Worker             len++;
365*8975f5c5SAndroid Build Coastguard Worker         }
366*8975f5c5SAndroid Build Coastguard Worker     }
367*8975f5c5SAndroid Build Coastguard Worker     y[len] = '\0';
368*8975f5c5SAndroid Build Coastguard Worker     return y;
369*8975f5c5SAndroid Build Coastguard Worker }
370*8975f5c5SAndroid Build Coastguard Worker //single argument function definitions
371*8975f5c5SAndroid Build Coastguard Worker double( * single_arg_fun[])(double) = {
372*8975f5c5SAndroid Build Coastguard Worker     // double_arg_fun (first three tokens are whitespace and parantheses)
373*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
374*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
375*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
376*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
377*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
378*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
379*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
380*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL,
381*8975f5c5SAndroid Build Coastguard Worker     // single_arg_fun
382*8975f5c5SAndroid Build Coastguard Worker     ceval_abs, ceval_exp, ceval_sqrt, ceval_cbrt,
383*8975f5c5SAndroid Build Coastguard Worker     ceval_ln, ceval_log10, ceval_ceil, ceval_floor,
384*8975f5c5SAndroid Build Coastguard Worker     ceval_signum, ceval_factorial, ceval_int_part, ceval_frac_part,
385*8975f5c5SAndroid Build Coastguard Worker     ceval_deg2rad, ceval_rad2deg, ceval_sin, ceval_cos,
386*8975f5c5SAndroid Build Coastguard Worker     ceval_tan, ceval_asin, ceval_acos, ceval_atan,
387*8975f5c5SAndroid Build Coastguard Worker     ceval_sinh, ceval_cosh, ceval_tanh, ceval_not,
388*8975f5c5SAndroid Build Coastguard Worker     ceval_bit_not, ceval_positive_sign, ceval_negative_sign,
389*8975f5c5SAndroid Build Coastguard Worker     // number and constant tokens
390*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL
391*8975f5c5SAndroid Build Coastguard Worker };
ceval_signum(double x)392*8975f5c5SAndroid Build Coastguard Worker double ceval_signum(double x) {
393*8975f5c5SAndroid Build Coastguard Worker     return (x == 0) ? 0 :
394*8975f5c5SAndroid Build Coastguard Worker         (x > 0) ? 1 :
395*8975f5c5SAndroid Build Coastguard Worker         -1;
396*8975f5c5SAndroid Build Coastguard Worker }
ceval_asin(double x)397*8975f5c5SAndroid Build Coastguard Worker double ceval_asin(double x) {
398*8975f5c5SAndroid Build Coastguard Worker     if (x > 1 || x < -1) {
399*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Numerical argument out of domain");
400*8975f5c5SAndroid Build Coastguard Worker         return NAN;
401*8975f5c5SAndroid Build Coastguard Worker     }
402*8975f5c5SAndroid Build Coastguard Worker     return asin(x);
403*8975f5c5SAndroid Build Coastguard Worker }
ceval_acos(double x)404*8975f5c5SAndroid Build Coastguard Worker double ceval_acos(double x) {
405*8975f5c5SAndroid Build Coastguard Worker     if (x > 1 || x < -1) {
406*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Numerical argument out of domain");
407*8975f5c5SAndroid Build Coastguard Worker         return NAN;
408*8975f5c5SAndroid Build Coastguard Worker     }
409*8975f5c5SAndroid Build Coastguard Worker     return acos(x);
410*8975f5c5SAndroid Build Coastguard Worker }
ceval_atan(double x)411*8975f5c5SAndroid Build Coastguard Worker double ceval_atan(double x) {
412*8975f5c5SAndroid Build Coastguard Worker     return atan(x);
413*8975f5c5SAndroid Build Coastguard Worker }
ceval_sin(double x)414*8975f5c5SAndroid Build Coastguard Worker double ceval_sin(double x) {
415*8975f5c5SAndroid Build Coastguard Worker     double sin_val = sin(x);
416*8975f5c5SAndroid Build Coastguard Worker     //sin(pi) == 0.000000, but sin(pi-CEVAL_EPSILON) == -0.00000* and sin(pi+CEVAL_EPSILON) == +0.00000*
417*8975f5c5SAndroid Build Coastguard Worker     //since the precision of pi (approx) is limited, it often leads to -0.0000 printed out as a result
418*8975f5c5SAndroid Build Coastguard Worker     //thus, we assumse 0.0000 value for all |sin(x)|<=CEVAL_EPSILON
419*8975f5c5SAndroid Build Coastguard Worker     return (fabs(sin_val) <= CEVAL_EPSILON) ? 0 : sin_val;
420*8975f5c5SAndroid Build Coastguard Worker }
ceval_cos(double x)421*8975f5c5SAndroid Build Coastguard Worker double ceval_cos(double x) {
422*8975f5c5SAndroid Build Coastguard Worker     double cos_val = cos(x);
423*8975f5c5SAndroid Build Coastguard Worker     return (fabs(cos_val) <= CEVAL_EPSILON) ? 0 : cos_val;
424*8975f5c5SAndroid Build Coastguard Worker }
ceval_tan(double x)425*8975f5c5SAndroid Build Coastguard Worker double ceval_tan(double x) {
426*8975f5c5SAndroid Build Coastguard Worker     double tan_val = tan(x);
427*8975f5c5SAndroid Build Coastguard Worker     if (fabs(ceval_modulus(x - CEVAL_PI / 2, CEVAL_PI, 0)) <= CEVAL_DELTA) {
428*8975f5c5SAndroid Build Coastguard Worker         ceval_error("tan() is not defined for odd-integral multiples of pi/2");
429*8975f5c5SAndroid Build Coastguard Worker         return NAN;
430*8975f5c5SAndroid Build Coastguard Worker     }
431*8975f5c5SAndroid Build Coastguard Worker     return (fabs(tan_val) <= CEVAL_EPSILON) ? 0 : tan_val;
432*8975f5c5SAndroid Build Coastguard Worker }
ceval_rad2deg(double x)433*8975f5c5SAndroid Build Coastguard Worker double ceval_rad2deg(double x) {
434*8975f5c5SAndroid Build Coastguard Worker     return x / CEVAL_PI * 180;
435*8975f5c5SAndroid Build Coastguard Worker }
ceval_deg2rad(double x)436*8975f5c5SAndroid Build Coastguard Worker double ceval_deg2rad(double x) {
437*8975f5c5SAndroid Build Coastguard Worker     return x / 180 * CEVAL_PI;
438*8975f5c5SAndroid Build Coastguard Worker }
ceval_int_part(double x)439*8975f5c5SAndroid Build Coastguard Worker double ceval_int_part(double x) {
440*8975f5c5SAndroid Build Coastguard Worker     double x_i;
441*8975f5c5SAndroid Build Coastguard Worker     modf(x, & x_i);
442*8975f5c5SAndroid Build Coastguard Worker     return x_i;
443*8975f5c5SAndroid Build Coastguard Worker }
ceval_frac_part(double x)444*8975f5c5SAndroid Build Coastguard Worker double ceval_frac_part(double x) {
445*8975f5c5SAndroid Build Coastguard Worker     double x_i, x_f;
446*8975f5c5SAndroid Build Coastguard Worker     x_f = modf(x, & x_i);
447*8975f5c5SAndroid Build Coastguard Worker     return x_f;
448*8975f5c5SAndroid Build Coastguard Worker }
ceval_log10(double x)449*8975f5c5SAndroid Build Coastguard Worker double ceval_log10(double x) {
450*8975f5c5SAndroid Build Coastguard Worker     return ceval_log(10, x, 0);
451*8975f5c5SAndroid Build Coastguard Worker }
ceval_ln(double x)452*8975f5c5SAndroid Build Coastguard Worker double ceval_ln(double x) {
453*8975f5c5SAndroid Build Coastguard Worker     return ceval_log(CEVAL_E, x, 0);
454*8975f5c5SAndroid Build Coastguard Worker }
ceval_exp(double x)455*8975f5c5SAndroid Build Coastguard Worker double ceval_exp(double x) {
456*8975f5c5SAndroid Build Coastguard Worker     return ceval_power(CEVAL_E, x, 0);
457*8975f5c5SAndroid Build Coastguard Worker }
ceval_factorial(double x)458*8975f5c5SAndroid Build Coastguard Worker double ceval_factorial(double x) {
459*8975f5c5SAndroid Build Coastguard Worker     if (x < 0) {
460*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Numerical argument out of domain");
461*8975f5c5SAndroid Build Coastguard Worker         return NAN;
462*8975f5c5SAndroid Build Coastguard Worker     }
463*8975f5c5SAndroid Build Coastguard Worker     return tgamma(x + 1);
464*8975f5c5SAndroid Build Coastguard Worker }
ceval_positive_sign(double x)465*8975f5c5SAndroid Build Coastguard Worker double ceval_positive_sign(double x) {
466*8975f5c5SAndroid Build Coastguard Worker     return x;
467*8975f5c5SAndroid Build Coastguard Worker }
ceval_negative_sign(double x)468*8975f5c5SAndroid Build Coastguard Worker double ceval_negative_sign(double x) {
469*8975f5c5SAndroid Build Coastguard Worker     return -x;
470*8975f5c5SAndroid Build Coastguard Worker }
ceval_abs(double x)471*8975f5c5SAndroid Build Coastguard Worker double ceval_abs(double x) {
472*8975f5c5SAndroid Build Coastguard Worker     return fabs(x);
473*8975f5c5SAndroid Build Coastguard Worker }
ceval_sqrt(double x)474*8975f5c5SAndroid Build Coastguard Worker double ceval_sqrt(double x) {
475*8975f5c5SAndroid Build Coastguard Worker     if (x >= 0) return sqrt(x);
476*8975f5c5SAndroid Build Coastguard Worker     ceval_error("sqrt(): can't operate on negative numbers");
477*8975f5c5SAndroid Build Coastguard Worker     return NAN;
478*8975f5c5SAndroid Build Coastguard Worker }
ceval_cbrt(double x)479*8975f5c5SAndroid Build Coastguard Worker double ceval_cbrt(double x) {
480*8975f5c5SAndroid Build Coastguard Worker     return cbrt(x);
481*8975f5c5SAndroid Build Coastguard Worker }
ceval_ceil(double x)482*8975f5c5SAndroid Build Coastguard Worker double ceval_ceil(double x) {
483*8975f5c5SAndroid Build Coastguard Worker     return ceil(x);
484*8975f5c5SAndroid Build Coastguard Worker }
ceval_floor(double x)485*8975f5c5SAndroid Build Coastguard Worker double ceval_floor(double x) {
486*8975f5c5SAndroid Build Coastguard Worker     return floor(x);
487*8975f5c5SAndroid Build Coastguard Worker }
ceval_sinh(double x)488*8975f5c5SAndroid Build Coastguard Worker double ceval_sinh(double x) {
489*8975f5c5SAndroid Build Coastguard Worker     return sinh(x);
490*8975f5c5SAndroid Build Coastguard Worker }
ceval_cosh(double x)491*8975f5c5SAndroid Build Coastguard Worker double ceval_cosh(double x) {
492*8975f5c5SAndroid Build Coastguard Worker     return cosh(x);
493*8975f5c5SAndroid Build Coastguard Worker }
ceval_tanh(double x)494*8975f5c5SAndroid Build Coastguard Worker double ceval_tanh(double x) {
495*8975f5c5SAndroid Build Coastguard Worker     return tanh(x);
496*8975f5c5SAndroid Build Coastguard Worker }
ceval_not(double x)497*8975f5c5SAndroid Build Coastguard Worker double ceval_not(double x) {
498*8975f5c5SAndroid Build Coastguard Worker     return (double) ! (int)x;
499*8975f5c5SAndroid Build Coastguard Worker }
ceval_bit_not(double x)500*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_not(double x) {
501*8975f5c5SAndroid Build Coastguard Worker     if(ceval_frac_part(x) == 0) {
502*8975f5c5SAndroid Build Coastguard Worker         return ~(int)x;
503*8975f5c5SAndroid Build Coastguard Worker     } else {
504*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_not(): operand must be of integral type");
505*8975f5c5SAndroid Build Coastguard Worker         return NAN;
506*8975f5c5SAndroid Build Coastguard Worker     }
507*8975f5c5SAndroid Build Coastguard Worker }
508*8975f5c5SAndroid Build Coastguard Worker //double argument function definitions
509*8975f5c5SAndroid Build Coastguard Worker double( * double_arg_fun[])(double, double, int) = {
510*8975f5c5SAndroid Build Coastguard Worker     // double_arg_fun (first three tokens are whitespace and parantheses)
511*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, ceval_comma,
512*8975f5c5SAndroid Build Coastguard Worker     ceval_or, ceval_and, ceval_bit_or, ceval_bit_xor,
513*8975f5c5SAndroid Build Coastguard Worker     ceval_bit_and, ceval_are_equal, ceval_not_equal, ceval_lesser,
514*8975f5c5SAndroid Build Coastguard Worker     ceval_greater, ceval_lesser_s, ceval_greater_s, ceval_bit_lshift,
515*8975f5c5SAndroid Build Coastguard Worker     ceval_bit_rshift, ceval_sum, ceval_diff, ceval_prod,
516*8975f5c5SAndroid Build Coastguard Worker     ceval_div, ceval_modulus, ceval_quotient, ceval_power,
517*8975f5c5SAndroid Build Coastguard Worker     ceval_gcd, ceval_hcf, ceval_lcm, ceval_log,
518*8975f5c5SAndroid Build Coastguard Worker     ceval_atan2, ceval_sci2dec, ceval_power,
519*8975f5c5SAndroid Build Coastguard Worker     // single_arg_fun
520*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
521*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
522*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
523*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
524*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
525*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL, NULL,
526*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL,
527*8975f5c5SAndroid Build Coastguard Worker     // number and constant tokens
528*8975f5c5SAndroid Build Coastguard Worker     NULL, NULL, NULL
529*8975f5c5SAndroid Build Coastguard Worker };
ceval_sum(double a,double b,int arg_check)530*8975f5c5SAndroid Build Coastguard Worker double ceval_sum(double a, double b, int arg_check) {
531*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
532*8975f5c5SAndroid Build Coastguard Worker         ceval_error("sum(): function takes two arguments");
533*8975f5c5SAndroid Build Coastguard Worker         return NAN;
534*8975f5c5SAndroid Build Coastguard Worker     }
535*8975f5c5SAndroid Build Coastguard Worker     return a + b;
536*8975f5c5SAndroid Build Coastguard Worker }
ceval_diff(double a,double b,int arg_check)537*8975f5c5SAndroid Build Coastguard Worker double ceval_diff(double a, double b, int arg_check) {
538*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
539*8975f5c5SAndroid Build Coastguard Worker         ceval_error("diff(): function takes two arguments");
540*8975f5c5SAndroid Build Coastguard Worker         return NAN;
541*8975f5c5SAndroid Build Coastguard Worker     }
542*8975f5c5SAndroid Build Coastguard Worker     return a - b;
543*8975f5c5SAndroid Build Coastguard Worker }
ceval_prod(double a,double b,int arg_check)544*8975f5c5SAndroid Build Coastguard Worker double ceval_prod(double a, double b, int arg_check) {
545*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
546*8975f5c5SAndroid Build Coastguard Worker         ceval_error("prod(): function takes two arguments");
547*8975f5c5SAndroid Build Coastguard Worker         return NAN;
548*8975f5c5SAndroid Build Coastguard Worker     }
549*8975f5c5SAndroid Build Coastguard Worker     return a * b;
550*8975f5c5SAndroid Build Coastguard Worker }
ceval_div(double a,double b,int arg_check)551*8975f5c5SAndroid Build Coastguard Worker double ceval_div(double a, double b, int arg_check) {
552*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
553*8975f5c5SAndroid Build Coastguard Worker         ceval_error("div(): function takes two arguments");
554*8975f5c5SAndroid Build Coastguard Worker         return NAN;
555*8975f5c5SAndroid Build Coastguard Worker     }
556*8975f5c5SAndroid Build Coastguard Worker     if (b == 0 && a == 0) {
557*8975f5c5SAndroid Build Coastguard Worker         ceval_error("0/0 is indeterminate...");
558*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Continuing evaluation with the assumption 0/0 = 1");
559*8975f5c5SAndroid Build Coastguard Worker         return 1;
560*8975f5c5SAndroid Build Coastguard Worker     } else if (b == 0) {
561*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Division by 0 is not defined...");
562*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Continuing evaluation with the assumption 1/0 = inf");
563*8975f5c5SAndroid Build Coastguard Worker         return a * INFINITY;
564*8975f5c5SAndroid Build Coastguard Worker     }
565*8975f5c5SAndroid Build Coastguard Worker     return a / b;
566*8975f5c5SAndroid Build Coastguard Worker }
ceval_modulus(double a,double b,int arg_check)567*8975f5c5SAndroid Build Coastguard Worker double ceval_modulus(double a, double b, int arg_check) {
568*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
569*8975f5c5SAndroid Build Coastguard Worker         ceval_error("modulo(): function takes two arguments");
570*8975f5c5SAndroid Build Coastguard Worker         return NAN;
571*8975f5c5SAndroid Build Coastguard Worker     }
572*8975f5c5SAndroid Build Coastguard Worker     if (b == 0) {
573*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Division by 0 is not defined...");
574*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Continuing evaluation with the assumption 1%0 = 0");
575*8975f5c5SAndroid Build Coastguard Worker         return 0;
576*8975f5c5SAndroid Build Coastguard Worker     }
577*8975f5c5SAndroid Build Coastguard Worker     return fmod(a, b);
578*8975f5c5SAndroid Build Coastguard Worker }
ceval_quotient(double a,double b,int arg_check)579*8975f5c5SAndroid Build Coastguard Worker double ceval_quotient(double a, double b, int arg_check) {
580*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
581*8975f5c5SAndroid Build Coastguard Worker         ceval_error("quotient(): function takes two arguments");
582*8975f5c5SAndroid Build Coastguard Worker         return NAN;
583*8975f5c5SAndroid Build Coastguard Worker     }
584*8975f5c5SAndroid Build Coastguard Worker     //a = b*q + r
585*8975f5c5SAndroid Build Coastguard Worker     //q = (a - r)/b
586*8975f5c5SAndroid Build Coastguard Worker     if (b == 0 && a == 0) {
587*8975f5c5SAndroid Build Coastguard Worker         ceval_error("0/0 is indeterminate...");
588*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Continuing evaluation with the assumption 0/0 = 1");
589*8975f5c5SAndroid Build Coastguard Worker         return 1;
590*8975f5c5SAndroid Build Coastguard Worker 
591*8975f5c5SAndroid Build Coastguard Worker     } else if (b == 0) {
592*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Division by 0 is not defined...");
593*8975f5c5SAndroid Build Coastguard Worker         ceval_error("Continuing evaluation with the assumption 1/0 = inf");
594*8975f5c5SAndroid Build Coastguard Worker         return a * INFINITY;
595*8975f5c5SAndroid Build Coastguard Worker     }
596*8975f5c5SAndroid Build Coastguard Worker     return (a - ceval_modulus(a, b, 0)) / b;
597*8975f5c5SAndroid Build Coastguard Worker }
ceval_gcd(double a,double b,int arg_check)598*8975f5c5SAndroid Build Coastguard Worker double ceval_gcd(double a, double b, int arg_check) {
599*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
600*8975f5c5SAndroid Build Coastguard Worker         ceval_error("gcd(): function takes two arguments");
601*8975f5c5SAndroid Build Coastguard Worker         return NAN;
602*8975f5c5SAndroid Build Coastguard Worker     }
603*8975f5c5SAndroid Build Coastguard Worker     double a_f = ceval_frac_part(a),
604*8975f5c5SAndroid Build Coastguard Worker         b_f = ceval_frac_part(b);
605*8975f5c5SAndroid Build Coastguard Worker     int a_i = (int)ceval_int_part(a),
606*8975f5c5SAndroid Build Coastguard Worker         b_i = (int)ceval_int_part(b);
607*8975f5c5SAndroid Build Coastguard Worker     if (a_f == 0 && b_f == 0) {
608*8975f5c5SAndroid Build Coastguard Worker         return (double) ceval_gcd_binary(a_i, b_i);
609*8975f5c5SAndroid Build Coastguard Worker     } else {
610*8975f5c5SAndroid Build Coastguard Worker         ceval_error("gcd() takes only integral parameters");
611*8975f5c5SAndroid Build Coastguard Worker         return NAN;
612*8975f5c5SAndroid Build Coastguard Worker     }
613*8975f5c5SAndroid Build Coastguard Worker }
ceval_hcf(double a,double b,int arg_check)614*8975f5c5SAndroid Build Coastguard Worker double ceval_hcf(double a, double b, int arg_check) {
615*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
616*8975f5c5SAndroid Build Coastguard Worker         ceval_error("hcf(): function takes two arguments");
617*8975f5c5SAndroid Build Coastguard Worker         return NAN;
618*8975f5c5SAndroid Build Coastguard Worker     }
619*8975f5c5SAndroid Build Coastguard Worker     return ceval_gcd(a, b, 0);
620*8975f5c5SAndroid Build Coastguard Worker }
ceval_lcm(double a,double b,int arg_check)621*8975f5c5SAndroid Build Coastguard Worker double ceval_lcm(double a, double b, int arg_check) {
622*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
623*8975f5c5SAndroid Build Coastguard Worker         ceval_error("lcm(): function takes two arguments");
624*8975f5c5SAndroid Build Coastguard Worker         return NAN;
625*8975f5c5SAndroid Build Coastguard Worker     }
626*8975f5c5SAndroid Build Coastguard Worker     return a * b / ceval_gcd(a, b, 0);
627*8975f5c5SAndroid Build Coastguard Worker }
ceval_log(double b,double x,int arg_check)628*8975f5c5SAndroid Build Coastguard Worker double ceval_log(double b, double x, int arg_check) {
629*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
630*8975f5c5SAndroid Build Coastguard Worker         ceval_error("log(): function takes two arguments");
631*8975f5c5SAndroid Build Coastguard Worker         return NAN;
632*8975f5c5SAndroid Build Coastguard Worker     }
633*8975f5c5SAndroid Build Coastguard Worker     if (b == 0) {
634*8975f5c5SAndroid Build Coastguard Worker         if (x == 0) {
635*8975f5c5SAndroid Build Coastguard Worker             ceval_error("log(0,0) is indeterminate");
636*8975f5c5SAndroid Build Coastguard Worker             return NAN;
637*8975f5c5SAndroid Build Coastguard Worker         } else {
638*8975f5c5SAndroid Build Coastguard Worker             return 0;
639*8975f5c5SAndroid Build Coastguard Worker         }
640*8975f5c5SAndroid Build Coastguard Worker     }
641*8975f5c5SAndroid Build Coastguard Worker     return log(x) / log(b);
642*8975f5c5SAndroid Build Coastguard Worker }
ceval_are_equal(double a,double b,int arg_check)643*8975f5c5SAndroid Build Coastguard Worker double ceval_are_equal(double a, double b, int arg_check) {
644*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
645*8975f5c5SAndroid Build Coastguard Worker         ceval_error("==: function takes two arguments");
646*8975f5c5SAndroid Build Coastguard Worker         return NAN;
647*8975f5c5SAndroid Build Coastguard Worker     }
648*8975f5c5SAndroid Build Coastguard Worker     if (fabs(a - b) <= CEVAL_EPSILON) {
649*8975f5c5SAndroid Build Coastguard Worker         return 1;
650*8975f5c5SAndroid Build Coastguard Worker     } else {
651*8975f5c5SAndroid Build Coastguard Worker         return 0;
652*8975f5c5SAndroid Build Coastguard Worker     }
653*8975f5c5SAndroid Build Coastguard Worker }
ceval_not_equal(double a,double b,int arg_check)654*8975f5c5SAndroid Build Coastguard Worker double ceval_not_equal(double a, double b, int arg_check) {
655*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
656*8975f5c5SAndroid Build Coastguard Worker         ceval_error("!=: function takes two arguments");
657*8975f5c5SAndroid Build Coastguard Worker         return NAN;
658*8975f5c5SAndroid Build Coastguard Worker     }
659*8975f5c5SAndroid Build Coastguard Worker     return (double)!(int)ceval_are_equal(a, b, 0);
660*8975f5c5SAndroid Build Coastguard Worker }
ceval_lesser(double a,double b,int arg_check)661*8975f5c5SAndroid Build Coastguard Worker double ceval_lesser(double a, double b, int arg_check) {
662*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
663*8975f5c5SAndroid Build Coastguard Worker         ceval_error("<=: function takes two arguments");
664*8975f5c5SAndroid Build Coastguard Worker         return NAN;
665*8975f5c5SAndroid Build Coastguard Worker     }
666*8975f5c5SAndroid Build Coastguard Worker     return (double)!(int)ceval_greater_s(a, b, 0);
667*8975f5c5SAndroid Build Coastguard Worker }
ceval_greater(double a,double b,int arg_check)668*8975f5c5SAndroid Build Coastguard Worker double ceval_greater(double a, double b, int arg_check) {
669*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
670*8975f5c5SAndroid Build Coastguard Worker         ceval_error(">=: function takes two arguments");
671*8975f5c5SAndroid Build Coastguard Worker         return NAN;
672*8975f5c5SAndroid Build Coastguard Worker     }
673*8975f5c5SAndroid Build Coastguard Worker     return (double)!(int)ceval_lesser_s(a, b, 0);
674*8975f5c5SAndroid Build Coastguard Worker }
ceval_lesser_s(double a,double b,int arg_check)675*8975f5c5SAndroid Build Coastguard Worker double ceval_lesser_s(double a, double b, int arg_check) {
676*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
677*8975f5c5SAndroid Build Coastguard Worker         ceval_error("<: function takes two arguments");
678*8975f5c5SAndroid Build Coastguard Worker         return NAN;
679*8975f5c5SAndroid Build Coastguard Worker     }
680*8975f5c5SAndroid Build Coastguard Worker     return (b - a) >= CEVAL_EPSILON;
681*8975f5c5SAndroid Build Coastguard Worker }
ceval_greater_s(double a,double b,int arg_check)682*8975f5c5SAndroid Build Coastguard Worker double ceval_greater_s(double a, double b, int arg_check) {
683*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
684*8975f5c5SAndroid Build Coastguard Worker         ceval_error(">: function takes two arguments");
685*8975f5c5SAndroid Build Coastguard Worker         return NAN;
686*8975f5c5SAndroid Build Coastguard Worker     }
687*8975f5c5SAndroid Build Coastguard Worker     return (a - b) >= CEVAL_EPSILON;
688*8975f5c5SAndroid Build Coastguard Worker }
ceval_comma(double x,double y,int arg_check)689*8975f5c5SAndroid Build Coastguard Worker double ceval_comma(double x, double y, int arg_check) {
690*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
691*8975f5c5SAndroid Build Coastguard Worker         ceval_error(",: function takes two arguments");
692*8975f5c5SAndroid Build Coastguard Worker         return NAN;
693*8975f5c5SAndroid Build Coastguard Worker     }
694*8975f5c5SAndroid Build Coastguard Worker     return y;
695*8975f5c5SAndroid Build Coastguard Worker }
ceval_power(double x,double y,int arg_check)696*8975f5c5SAndroid Build Coastguard Worker double ceval_power(double x, double y, int arg_check) {
697*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
698*8975f5c5SAndroid Build Coastguard Worker         ceval_error("pow(): function takes two arguments");
699*8975f5c5SAndroid Build Coastguard Worker         return NAN;
700*8975f5c5SAndroid Build Coastguard Worker     }
701*8975f5c5SAndroid Build Coastguard Worker     if(x<0 && ceval_frac_part(y)!=0) {
702*8975f5c5SAndroid Build Coastguard Worker         ceval_error("pow(): negative numbers can only be raised to integral powers");
703*8975f5c5SAndroid Build Coastguard Worker         return NAN;
704*8975f5c5SAndroid Build Coastguard Worker     }
705*8975f5c5SAndroid Build Coastguard Worker     return pow(x, y);
706*8975f5c5SAndroid Build Coastguard Worker }
ceval_atan2(double x,double y,int arg_check)707*8975f5c5SAndroid Build Coastguard Worker double ceval_atan2(double x, double y, int arg_check) {
708*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
709*8975f5c5SAndroid Build Coastguard Worker         ceval_error("atan2(): function takes two arguments");
710*8975f5c5SAndroid Build Coastguard Worker         return NAN;
711*8975f5c5SAndroid Build Coastguard Worker     }
712*8975f5c5SAndroid Build Coastguard Worker     return atan2(x, y);
713*8975f5c5SAndroid Build Coastguard Worker }
ceval_sci2dec(double m,double e,int arg_check)714*8975f5c5SAndroid Build Coastguard Worker double ceval_sci2dec(double m, double e, int arg_check) {
715*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
716*8975f5c5SAndroid Build Coastguard Worker         ceval_error("sci2dec(): function takes two arguments");
717*8975f5c5SAndroid Build Coastguard Worker         return NAN;
718*8975f5c5SAndroid Build Coastguard Worker     }
719*8975f5c5SAndroid Build Coastguard Worker     return (double) m * ceval_power(10, e, 0);
720*8975f5c5SAndroid Build Coastguard Worker }
ceval_and(double x,double y,int arg_check)721*8975f5c5SAndroid Build Coastguard Worker double ceval_and(double x, double y, int arg_check) {
722*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
723*8975f5c5SAndroid Build Coastguard Worker         ceval_error("and(): function takes two arguments");
724*8975f5c5SAndroid Build Coastguard Worker         return NAN;
725*8975f5c5SAndroid Build Coastguard Worker     }
726*8975f5c5SAndroid Build Coastguard Worker     return (double) ((int)x && (int)y);
727*8975f5c5SAndroid Build Coastguard Worker }
ceval_or(double x,double y,int arg_check)728*8975f5c5SAndroid Build Coastguard Worker double ceval_or(double x, double y, int arg_check) {
729*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
730*8975f5c5SAndroid Build Coastguard Worker         ceval_error("or(): function takes two arguments");
731*8975f5c5SAndroid Build Coastguard Worker         return NAN;
732*8975f5c5SAndroid Build Coastguard Worker     }
733*8975f5c5SAndroid Build Coastguard Worker     return (double) ((int)x || (int)y);
734*8975f5c5SAndroid Build Coastguard Worker }
ceval_bit_and(double x,double y,int arg_check)735*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_and(double x, double y, int arg_check) {
736*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
737*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_and(): function takes two arguments");
738*8975f5c5SAndroid Build Coastguard Worker         return NAN;
739*8975f5c5SAndroid Build Coastguard Worker     }
740*8975f5c5SAndroid Build Coastguard Worker     if(ceval_frac_part(x) == 0 && ceval_frac_part(y) == 0) {
741*8975f5c5SAndroid Build Coastguard Worker         return (int)x & (int)y;
742*8975f5c5SAndroid Build Coastguard Worker     } else {
743*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_and(): operands must be of integral type");
744*8975f5c5SAndroid Build Coastguard Worker         return NAN;
745*8975f5c5SAndroid Build Coastguard Worker     }
746*8975f5c5SAndroid Build Coastguard Worker }
ceval_bit_xor(double x,double y,int arg_check)747*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_xor(double x, double y, int arg_check) {
748*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
749*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_xor(): function takes two arguments");
750*8975f5c5SAndroid Build Coastguard Worker         return NAN;
751*8975f5c5SAndroid Build Coastguard Worker     }
752*8975f5c5SAndroid Build Coastguard Worker     if(ceval_frac_part(x) == 0 && ceval_frac_part(y) == 0) {
753*8975f5c5SAndroid Build Coastguard Worker         return (int)x ^ (int)y;
754*8975f5c5SAndroid Build Coastguard Worker     } else {
755*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_xor(): operands must be of integral type");
756*8975f5c5SAndroid Build Coastguard Worker         return NAN;
757*8975f5c5SAndroid Build Coastguard Worker     }
758*8975f5c5SAndroid Build Coastguard Worker }
ceval_bit_or(double x,double y,int arg_check)759*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_or(double x, double y, int arg_check) {
760*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
761*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_or(): function takes two arguments");
762*8975f5c5SAndroid Build Coastguard Worker         return NAN;
763*8975f5c5SAndroid Build Coastguard Worker     }
764*8975f5c5SAndroid Build Coastguard Worker     if(ceval_frac_part(x) == 0 && ceval_frac_part(y) == 0) {
765*8975f5c5SAndroid Build Coastguard Worker         return (int)x | (int)y;
766*8975f5c5SAndroid Build Coastguard Worker     } else {
767*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_or(): operands must be of integral type");
768*8975f5c5SAndroid Build Coastguard Worker         return NAN;
769*8975f5c5SAndroid Build Coastguard Worker     }
770*8975f5c5SAndroid Build Coastguard Worker }
ceval_bit_lshift(double x,double y,int arg_check)771*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_lshift(double x, double y, int arg_check) {
772*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
773*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_lshift(): function takes two arguments");
774*8975f5c5SAndroid Build Coastguard Worker         return NAN;
775*8975f5c5SAndroid Build Coastguard Worker     }
776*8975f5c5SAndroid Build Coastguard Worker     if(ceval_frac_part(x) == 0 && ceval_frac_part(y) == 0) {
777*8975f5c5SAndroid Build Coastguard Worker         return (int)x << (int)y;
778*8975f5c5SAndroid Build Coastguard Worker     } else {
779*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_lshift(): operands must be of integral type");
780*8975f5c5SAndroid Build Coastguard Worker         return NAN;
781*8975f5c5SAndroid Build Coastguard Worker     }
782*8975f5c5SAndroid Build Coastguard Worker 
783*8975f5c5SAndroid Build Coastguard Worker }
ceval_bit_rshift(double x,double y,int arg_check)784*8975f5c5SAndroid Build Coastguard Worker double ceval_bit_rshift(double x, double y, int arg_check) {
785*8975f5c5SAndroid Build Coastguard Worker     if (arg_check) {
786*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_rshift(): function takes two arguments");
787*8975f5c5SAndroid Build Coastguard Worker         return NAN;
788*8975f5c5SAndroid Build Coastguard Worker     }
789*8975f5c5SAndroid Build Coastguard Worker     if(ceval_frac_part(x) == 0 && ceval_frac_part(y) == 0) {
790*8975f5c5SAndroid Build Coastguard Worker         return (int)x >> (int)y;
791*8975f5c5SAndroid Build Coastguard Worker     } else {
792*8975f5c5SAndroid Build Coastguard Worker         ceval_error("bit_rshift(): operands must be of integral type");
793*8975f5c5SAndroid Build Coastguard Worker         return NAN;
794*8975f5c5SAndroid Build Coastguard Worker     }
795*8975f5c5SAndroid Build Coastguard Worker }
796*8975f5c5SAndroid Build Coastguard Worker /**************************************** !FUNCTIONS ********************************************/
797*8975f5c5SAndroid Build Coastguard Worker 
798*8975f5c5SAndroid Build Coastguard Worker /***************************************** PARSE_TREE_CONSTRUCTION *******************************************/
799*8975f5c5SAndroid Build Coastguard Worker void * ceval_make_tree(char * );
800*8975f5c5SAndroid Build Coastguard Worker ceval_node * ceval_insert_node(ceval_node * , ceval_node, int);
801*8975f5c5SAndroid Build Coastguard Worker void ceval_print_tree(const void * );
802*8975f5c5SAndroid Build Coastguard Worker void ceval_print_node(const ceval_node * , int);
803*8975f5c5SAndroid Build Coastguard Worker void ceval_delete_node(ceval_node * );
804*8975f5c5SAndroid Build Coastguard Worker void ceval_delete_tree(void * );
805*8975f5c5SAndroid Build Coastguard Worker 
ceval_delete_node(ceval_node * node)806*8975f5c5SAndroid Build Coastguard Worker void ceval_delete_node(ceval_node * node) {
807*8975f5c5SAndroid Build Coastguard Worker     if (!node) return;
808*8975f5c5SAndroid Build Coastguard Worker     ceval_delete_node(node -> left);
809*8975f5c5SAndroid Build Coastguard Worker     ceval_delete_node(node -> right);
810*8975f5c5SAndroid Build Coastguard Worker     free(node);
811*8975f5c5SAndroid Build Coastguard Worker }
ceval_delete_tree(void * tree)812*8975f5c5SAndroid Build Coastguard Worker void ceval_delete_tree(void * tree) {
813*8975f5c5SAndroid Build Coastguard Worker     ceval_delete_node((ceval_node * ) tree);
814*8975f5c5SAndroid Build Coastguard Worker }
ceval_insert_node(ceval_node * current,ceval_node item,int isRightAssoc)815*8975f5c5SAndroid Build Coastguard Worker ceval_node * ceval_insert_node(ceval_node * current, ceval_node item, int isRightAssoc) {
816*8975f5c5SAndroid Build Coastguard Worker     if (item.id != CEVAL_OPENPAR &&
817*8975f5c5SAndroid Build Coastguard Worker         item.id != CEVAL_NEGSIGN &&
818*8975f5c5SAndroid Build Coastguard Worker         item.id != CEVAL_POSSIGN) {
819*8975f5c5SAndroid Build Coastguard Worker         if (isRightAssoc) {
820*8975f5c5SAndroid Build Coastguard Worker             while (current -> pre > item.pre) {
821*8975f5c5SAndroid Build Coastguard Worker                 current = current -> parent;
822*8975f5c5SAndroid Build Coastguard Worker             }
823*8975f5c5SAndroid Build Coastguard Worker         } else {
824*8975f5c5SAndroid Build Coastguard Worker             while (current -> pre >= item.pre) {
825*8975f5c5SAndroid Build Coastguard Worker                 current = current -> parent;
826*8975f5c5SAndroid Build Coastguard Worker             }
827*8975f5c5SAndroid Build Coastguard Worker         }
828*8975f5c5SAndroid Build Coastguard Worker     }
829*8975f5c5SAndroid Build Coastguard Worker     if (item.id == CEVAL_CLOSEPAR) {
830*8975f5c5SAndroid Build Coastguard Worker         ceval_node * parent_of_openpar = current -> parent;
831*8975f5c5SAndroid Build Coastguard Worker         parent_of_openpar -> right = current -> right;
832*8975f5c5SAndroid Build Coastguard Worker         if (current -> right) current -> right -> parent = parent_of_openpar;
833*8975f5c5SAndroid Build Coastguard Worker         free(current);
834*8975f5c5SAndroid Build Coastguard Worker         current = parent_of_openpar;
835*8975f5c5SAndroid Build Coastguard Worker 
836*8975f5c5SAndroid Build Coastguard Worker         if (current -> right -> id == CEVAL_COMMA &&
837*8975f5c5SAndroid Build Coastguard Worker             ceval_is_binary_fun(current -> id)) {
838*8975f5c5SAndroid Build Coastguard Worker             ceval_node * address_of_comma = current -> right;
839*8975f5c5SAndroid Build Coastguard Worker             parent_of_openpar -> left = address_of_comma -> left;
840*8975f5c5SAndroid Build Coastguard Worker             address_of_comma -> left -> parent = parent_of_openpar;
841*8975f5c5SAndroid Build Coastguard Worker             parent_of_openpar -> right = address_of_comma -> right;
842*8975f5c5SAndroid Build Coastguard Worker             address_of_comma -> right -> parent = parent_of_openpar;
843*8975f5c5SAndroid Build Coastguard Worker             free(address_of_comma);
844*8975f5c5SAndroid Build Coastguard Worker         }
845*8975f5c5SAndroid Build Coastguard Worker         return current;
846*8975f5c5SAndroid Build Coastguard Worker     }
847*8975f5c5SAndroid Build Coastguard Worker     ceval_node * newnode = (ceval_node * ) malloc(sizeof(ceval_node));
848*8975f5c5SAndroid Build Coastguard Worker     * newnode = item;
849*8975f5c5SAndroid Build Coastguard Worker     newnode -> right = NULL;
850*8975f5c5SAndroid Build Coastguard Worker 
851*8975f5c5SAndroid Build Coastguard Worker     newnode -> left = current -> right;
852*8975f5c5SAndroid Build Coastguard Worker     if (current -> right) current -> right -> parent = newnode;
853*8975f5c5SAndroid Build Coastguard Worker     current -> right = newnode;
854*8975f5c5SAndroid Build Coastguard Worker     newnode -> parent = current;
855*8975f5c5SAndroid Build Coastguard Worker     current = newnode;
856*8975f5c5SAndroid Build Coastguard Worker     return current;
857*8975f5c5SAndroid Build Coastguard Worker }
858*8975f5c5SAndroid Build Coastguard Worker 
ceval_make_tree(char * expression)859*8975f5c5SAndroid Build Coastguard Worker void * ceval_make_tree(char * expression) {
860*8975f5c5SAndroid Build Coastguard Worker     if (expression == NULL) return NULL;
861*8975f5c5SAndroid Build Coastguard Worker     strcpy(expression, ceval_shrink(expression));
862*8975f5c5SAndroid Build Coastguard Worker     ceval_node root = {
863*8975f5c5SAndroid Build Coastguard Worker         CEVAL_OPENPAR,
864*8975f5c5SAndroid Build Coastguard Worker         ceval_token_prec(CEVAL_OPENPAR),
865*8975f5c5SAndroid Build Coastguard Worker         0,
866*8975f5c5SAndroid Build Coastguard Worker         NULL,
867*8975f5c5SAndroid Build Coastguard Worker         NULL,
868*8975f5c5SAndroid Build Coastguard Worker         NULL
869*8975f5c5SAndroid Build Coastguard Worker     };
870*8975f5c5SAndroid Build Coastguard Worker     ceval_node_id previous_id = CEVAL_OPENPAR;
871*8975f5c5SAndroid Build Coastguard Worker     ceval_node * current = & root;
872*8975f5c5SAndroid Build Coastguard Worker     int isRightAssoc = 0;
873*8975f5c5SAndroid Build Coastguard Worker     while (1) {
874*8975f5c5SAndroid Build Coastguard Worker         ceval_node node;
875*8975f5c5SAndroid Build Coastguard Worker         char c = * expression++;
876*8975f5c5SAndroid Build Coastguard Worker         if (c == '\0') break;
877*8975f5c5SAndroid Build Coastguard Worker         int token_found = -1;
878*8975f5c5SAndroid Build Coastguard Worker         char token[50];
879*8975f5c5SAndroid Build Coastguard Worker         unsigned int len = 0;
880*8975f5c5SAndroid Build Coastguard Worker         for(unsigned int i = 0; i < CEVAL_TOKEN_TABLE_SIZE; i++) {
881*8975f5c5SAndroid Build Coastguard Worker             strcpy(token, ceval_token_info[i].symbol);
882*8975f5c5SAndroid Build Coastguard Worker             len = (unsigned int) strlen(token);
883*8975f5c5SAndroid Build Coastguard Worker             if (!memcmp(expression - 1, token, len)) {
884*8975f5c5SAndroid Build Coastguard Worker                 token_found = ceval_token_info[i].id;
885*8975f5c5SAndroid Build Coastguard Worker                 isRightAssoc = (token_found == CEVAL_POW || token_found == CEVAL_CLOSEPAR ) ? 1 : 0;
886*8975f5c5SAndroid Build Coastguard Worker                 break;
887*8975f5c5SAndroid Build Coastguard Worker             }
888*8975f5c5SAndroid Build Coastguard Worker         }
889*8975f5c5SAndroid Build Coastguard Worker         // if token is found
890*8975f5c5SAndroid Build Coastguard Worker         if (token_found > -1) {
891*8975f5c5SAndroid Build Coastguard Worker             // check if the token is a binary operator
892*8975f5c5SAndroid Build Coastguard Worker             if (ceval_is_binary_opr((ceval_node_id)token_found)) {
893*8975f5c5SAndroid Build Coastguard Worker                 // a binary operator must be preceded by a number, a numerical constant, a clospar, or a factorial
894*8975f5c5SAndroid Build Coastguard Worker                 if (previous_id == CEVAL_NUMBER ||
895*8975f5c5SAndroid Build Coastguard Worker                     previous_id == CEVAL_CONST_PI ||
896*8975f5c5SAndroid Build Coastguard Worker                     previous_id == CEVAL_CONST_E ||
897*8975f5c5SAndroid Build Coastguard Worker                     previous_id == CEVAL_CLOSEPAR) {
898*8975f5c5SAndroid Build Coastguard Worker                     // other tokens (other than CEVAL_NUMBER, CEVAL_CLOSEPAR) are allowed only before '+'s or '-'s
899*8975f5c5SAndroid Build Coastguard Worker                     expression = expression + (len - 1);
900*8975f5c5SAndroid Build Coastguard Worker                     node.id = (ceval_node_id)token_found;
901*8975f5c5SAndroid Build Coastguard Worker                     node.pre = ceval_token_prec(node.id);
902*8975f5c5SAndroid Build Coastguard Worker                 } else {
903*8975f5c5SAndroid Build Coastguard Worker                     // if the operator is not preceded by a number, a numerical constant, a closepar, or a factorial, then check if the
904*8975f5c5SAndroid Build Coastguard Worker                     // character is a sign ('+' or '-')
905*8975f5c5SAndroid Build Coastguard Worker                     if (c == '+') {
906*8975f5c5SAndroid Build Coastguard Worker                         node.id = CEVAL_POSSIGN;
907*8975f5c5SAndroid Build Coastguard Worker                         node.pre = ceval_token_prec(node.id);
908*8975f5c5SAndroid Build Coastguard Worker                     } else if (c == '-') {
909*8975f5c5SAndroid Build Coastguard Worker                         node.id = CEVAL_NEGSIGN;
910*8975f5c5SAndroid Build Coastguard Worker                         node.pre = ceval_token_prec(node.id);
911*8975f5c5SAndroid Build Coastguard Worker                     } else {
912*8975f5c5SAndroid Build Coastguard Worker                         // if it is not a sign, then it must be a misplaced character
913*8975f5c5SAndroid Build Coastguard Worker                         ceval_error("Misplaced '%c'.", c);
914*8975f5c5SAndroid Build Coastguard Worker                         ceval_delete_tree(root.right);
915*8975f5c5SAndroid Build Coastguard Worker                         root.right = NULL;
916*8975f5c5SAndroid Build Coastguard Worker                         return NULL;
917*8975f5c5SAndroid Build Coastguard Worker                     }
918*8975f5c5SAndroid Build Coastguard Worker                 }
919*8975f5c5SAndroid Build Coastguard Worker             } else if (token_found == CEVAL_NUMBER){
920*8975f5c5SAndroid Build Coastguard Worker                 // if the token is a number, then store it in an array
921*8975f5c5SAndroid Build Coastguard Worker                 node.pre = ceval_token_prec(CEVAL_NUMBER);
922*8975f5c5SAndroid Build Coastguard Worker                 unsigned int i;
923*8975f5c5SAndroid Build Coastguard Worker                 char number[CEVAL_MAX_DIGITS];
924*8975f5c5SAndroid Build Coastguard Worker                 for (i = 0; i + 1 < sizeof(number);) {
925*8975f5c5SAndroid Build Coastguard Worker                     number[i++] = c;
926*8975f5c5SAndroid Build Coastguard Worker                     c = * expression;
927*8975f5c5SAndroid Build Coastguard Worker                     if (('0' <= c && c <= '9') ||
928*8975f5c5SAndroid Build Coastguard Worker                                           c == '.')
929*8975f5c5SAndroid Build Coastguard Worker                         expression++;
930*8975f5c5SAndroid Build Coastguard Worker                     else
931*8975f5c5SAndroid Build Coastguard Worker                         break;
932*8975f5c5SAndroid Build Coastguard Worker                 }
933*8975f5c5SAndroid Build Coastguard Worker                 number[i] = '\0';
934*8975f5c5SAndroid Build Coastguard Worker                 //copy the contents of the number array at &node.number
935*8975f5c5SAndroid Build Coastguard Worker                 sscanf(number, "%lf", & node.number);
936*8975f5c5SAndroid Build Coastguard Worker                 node.id = CEVAL_NUMBER;
937*8975f5c5SAndroid Build Coastguard Worker                 goto END;
938*8975f5c5SAndroid Build Coastguard Worker             } else if (token_found == CEVAL_WHITESPACE) {
939*8975f5c5SAndroid Build Coastguard Worker                 // skip whitespace
940*8975f5c5SAndroid Build Coastguard Worker                 continue;
941*8975f5c5SAndroid Build Coastguard Worker             } else {
942*8975f5c5SAndroid Build Coastguard Worker                 // for any other token
943*8975f5c5SAndroid Build Coastguard Worker                 expression = expression + (len - 1);
944*8975f5c5SAndroid Build Coastguard Worker                 node.id = (ceval_node_id)token_found;
945*8975f5c5SAndroid Build Coastguard Worker                 node.pre = ceval_token_prec(node.id);
946*8975f5c5SAndroid Build Coastguard Worker                 if (node.id == CEVAL_CONST_PI || node.id == CEVAL_CONST_E) {
947*8975f5c5SAndroid Build Coastguard Worker                     node.number = (node.id == CEVAL_CONST_PI) ? CEVAL_PI : CEVAL_E;
948*8975f5c5SAndroid Build Coastguard Worker                 }
949*8975f5c5SAndroid Build Coastguard Worker             }
950*8975f5c5SAndroid Build Coastguard Worker         } else {
951*8975f5c5SAndroid Build Coastguard Worker             // if the token is not found in the token table
952*8975f5c5SAndroid Build Coastguard Worker             ceval_error("Unknown token '%c'.", c);
953*8975f5c5SAndroid Build Coastguard Worker             ceval_delete_tree(root.right);
954*8975f5c5SAndroid Build Coastguard Worker             root.right = NULL;
955*8975f5c5SAndroid Build Coastguard Worker             return NULL;
956*8975f5c5SAndroid Build Coastguard Worker         }
957*8975f5c5SAndroid Build Coastguard Worker         END: ;
958*8975f5c5SAndroid Build Coastguard Worker         previous_id = node.id;
959*8975f5c5SAndroid Build Coastguard Worker         current = ceval_insert_node(current, node, isRightAssoc);
960*8975f5c5SAndroid Build Coastguard Worker     }
961*8975f5c5SAndroid Build Coastguard Worker     if (root.right) root.right -> parent = NULL;
962*8975f5c5SAndroid Build Coastguard Worker     return root.right;
963*8975f5c5SAndroid Build Coastguard Worker }
ceval_print_node(const ceval_node * node,int indent)964*8975f5c5SAndroid Build Coastguard Worker void ceval_print_node(const ceval_node * node, int indent) {
965*8975f5c5SAndroid Build Coastguard Worker     int i;
966*8975f5c5SAndroid Build Coastguard Worker     char number[CEVAL_MAX_DIGITS];
967*8975f5c5SAndroid Build Coastguard Worker     const char * str;
968*8975f5c5SAndroid Build Coastguard Worker     if (!node) return;
969*8975f5c5SAndroid Build Coastguard Worker     ceval_print_node(node -> right, indent + 4);
970*8975f5c5SAndroid Build Coastguard Worker     if (node -> id == CEVAL_NUMBER) {
971*8975f5c5SAndroid Build Coastguard Worker         if ((long) node -> number == node -> number) //for integers, skip the trailing zeroes
972*8975f5c5SAndroid Build Coastguard Worker             snprintf(number, sizeof(number), "%.0f", node -> number);
973*8975f5c5SAndroid Build Coastguard Worker         else snprintf(number, sizeof(number), "%.2f", node -> number);
974*8975f5c5SAndroid Build Coastguard Worker         str = number;
975*8975f5c5SAndroid Build Coastguard Worker     } else {
976*8975f5c5SAndroid Build Coastguard Worker         str = ceval_token_symbol(node -> id);
977*8975f5c5SAndroid Build Coastguard Worker     }
978*8975f5c5SAndroid Build Coastguard Worker     for (i = 0; i < indent; i++) {
979*8975f5c5SAndroid Build Coastguard Worker         putchar(' ');
980*8975f5c5SAndroid Build Coastguard Worker         putchar(' ');
981*8975f5c5SAndroid Build Coastguard Worker     }
982*8975f5c5SAndroid Build Coastguard Worker     printf("%s\n", str);
983*8975f5c5SAndroid Build Coastguard Worker     ceval_print_node(node -> left, indent + 4);
984*8975f5c5SAndroid Build Coastguard Worker }
ceval_print_tree(const void * tree)985*8975f5c5SAndroid Build Coastguard Worker void ceval_print_tree(const void * tree) {
986*8975f5c5SAndroid Build Coastguard Worker     ceval_print_node((const ceval_node * ) tree, 0);
987*8975f5c5SAndroid Build Coastguard Worker }
988*8975f5c5SAndroid Build Coastguard Worker /***************************************** !PARSE_TREE_CONSTRUCTION *******************************************/
989*8975f5c5SAndroid Build Coastguard Worker 
990*8975f5c5SAndroid Build Coastguard Worker /***************************************** EVALUATION *******************************************/
991*8975f5c5SAndroid Build Coastguard Worker double ceval_evaluate_tree_(const ceval_node * );
992*8975f5c5SAndroid Build Coastguard Worker double ceval_evaluate_tree(const void * );
993*8975f5c5SAndroid Build Coastguard Worker 
ceval_evaluate_tree_(const ceval_node * node)994*8975f5c5SAndroid Build Coastguard Worker double ceval_evaluate_tree_(const ceval_node * node) {
995*8975f5c5SAndroid Build Coastguard Worker     if (!node)
996*8975f5c5SAndroid Build Coastguard Worker         return 0;
997*8975f5c5SAndroid Build Coastguard Worker 
998*8975f5c5SAndroid Build Coastguard Worker     double left, right;
999*8975f5c5SAndroid Build Coastguard Worker     left = ceval_evaluate_tree_(node -> left);
1000*8975f5c5SAndroid Build Coastguard Worker     right = ceval_evaluate_tree_(node -> right);
1001*8975f5c5SAndroid Build Coastguard Worker     switch (node -> id) {
1002*8975f5c5SAndroid Build Coastguard Worker 
1003*8975f5c5SAndroid Build Coastguard Worker         //unary-right operators/functions (operate on the expression to their right)
1004*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_ABS: case CEVAL_EXP: case CEVAL_SQRT: case CEVAL_CBRT:
1005*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_LN: case CEVAL_LOG10: case CEVAL_CEIL: case CEVAL_FLOOR:
1006*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_SIGNUM: case CEVAL_FACTORIAL: case CEVAL_INT: case CEVAL_FRAC:
1007*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_DEG2RAD: case CEVAL_RAD2DEG: case CEVAL_SIN: case CEVAL_COS:
1008*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_TAN: case CEVAL_ASIN: case CEVAL_ACOS: case CEVAL_ATAN:
1009*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_SINH: case CEVAL_COSH: case CEVAL_TANH: case CEVAL_NOT:
1010*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_BIT_NOT: case CEVAL_POSSIGN: case CEVAL_NEGSIGN:
1011*8975f5c5SAndroid Build Coastguard Worker             if (node -> right != NULL) {
1012*8975f5c5SAndroid Build Coastguard Worker                 //operate on right operand
1013*8975f5c5SAndroid Build Coastguard Worker                 return ( * single_arg_fun[node -> id])(right);
1014*8975f5c5SAndroid Build Coastguard Worker             } else {
1015*8975f5c5SAndroid Build Coastguard Worker                 ceval_error("Missing operand(s)");
1016*8975f5c5SAndroid Build Coastguard Worker                 return NAN;
1017*8975f5c5SAndroid Build Coastguard Worker             }
1018*8975f5c5SAndroid Build Coastguard Worker         //binary operators/functions
1019*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_COMMA:
1020*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_OR:  case CEVAL_AND:  case CEVAL_BIT_OR:  case CEVAL_BIT_XOR:
1021*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_BIT_AND:  case CEVAL_EQUAL:  case CEVAL_NOTEQUAL: case CEVAL_LESSER:
1022*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_GREATER:  case CEVAL_LESSER_S:  case CEVAL_GREATER_S:  case CEVAL_BIT_LSHIFT:
1023*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_BIT_RSHIFT:  case CEVAL_PLUS:  case CEVAL_MINUS:  case CEVAL_TIMES:
1024*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_DIVIDE:  case CEVAL_MODULO:  case CEVAL_QUOTIENT:  case CEVAL_POW:
1025*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_GCD:  case CEVAL_HCF:  case CEVAL_LCM:  case CEVAL_LOG:
1026*8975f5c5SAndroid Build Coastguard Worker         case CEVAL_ATAN2:  case CEVAL_SCI2DEC: case CEVAL_POWFUN:
1027*8975f5c5SAndroid Build Coastguard Worker             if (node -> left == NULL) {
1028*8975f5c5SAndroid Build Coastguard Worker                 return ( * double_arg_fun[node -> id])(left, right, -1);
1029*8975f5c5SAndroid Build Coastguard Worker             } else if (node -> right == NULL) {
1030*8975f5c5SAndroid Build Coastguard Worker                 return ( * double_arg_fun[node -> id])(left, right, 1);
1031*8975f5c5SAndroid Build Coastguard Worker             } else {
1032*8975f5c5SAndroid Build Coastguard Worker                 return ( * double_arg_fun[node -> id])(left, right, 0);
1033*8975f5c5SAndroid Build Coastguard Worker             }
1034*8975f5c5SAndroid Build Coastguard Worker             default:
1035*8975f5c5SAndroid Build Coastguard Worker                 return node -> number;
1036*8975f5c5SAndroid Build Coastguard Worker     }
1037*8975f5c5SAndroid Build Coastguard Worker }
ceval_evaluate_tree(const void * node)1038*8975f5c5SAndroid Build Coastguard Worker double ceval_evaluate_tree(const void * node) {
1039*8975f5c5SAndroid Build Coastguard Worker     return (node == NULL)? NAN :
1040*8975f5c5SAndroid Build Coastguard Worker             ceval_evaluate_tree_((ceval_node * ) node);
1041*8975f5c5SAndroid Build Coastguard Worker }
1042*8975f5c5SAndroid Build Coastguard Worker /***************************************** !EVALUATION *******************************************/
1043*8975f5c5SAndroid Build Coastguard Worker 
1044*8975f5c5SAndroid Build Coastguard Worker /***************************************** MAIN FUNCTIONS *******************************************/
1045*8975f5c5SAndroid Build Coastguard Worker // functions accessible from main()
1046*8975f5c5SAndroid Build Coastguard Worker // - double ceval_result(char * inp) returns the result of valid math expression stored as a char array `inp`
1047*8975f5c5SAndroid Build Coastguard Worker // - void ceval_tree(char * inp) prints the parse tree for the input expression `inp`
1048*8975f5c5SAndroid Build Coastguard Worker // - define CEVAL_EPSILON (default value : 1e-2), CEVAL_DELTA (default value : 1e-6) and CEVAL_MAX_DIGITS (default value : 15) manually before the include directive
1049*8975f5c5SAndroid Build Coastguard Worker // - define CEVAL_STOICAL before the #include directive to use the parser/evaluator in stoical (non-complaining) mode. It suppresses all the error messages from [ceval].
1050*8975f5c5SAndroid Build Coastguard Worker 
ceval_result(char * expr)1051*8975f5c5SAndroid Build Coastguard Worker double ceval_result(char * expr) {
1052*8975f5c5SAndroid Build Coastguard Worker     void * tree = ceval_make_tree(expr);
1053*8975f5c5SAndroid Build Coastguard Worker     double result = ceval_evaluate_tree(tree);
1054*8975f5c5SAndroid Build Coastguard Worker     ceval_delete_tree(tree);
1055*8975f5c5SAndroid Build Coastguard Worker     return result;
1056*8975f5c5SAndroid Build Coastguard Worker }
ceval_tree(char * expr)1057*8975f5c5SAndroid Build Coastguard Worker void ceval_tree(char * expr) {
1058*8975f5c5SAndroid Build Coastguard Worker     void * tree = ceval_make_tree(expr);
1059*8975f5c5SAndroid Build Coastguard Worker     ceval_print_tree(tree);
1060*8975f5c5SAndroid Build Coastguard Worker     ceval_delete_tree(tree);
1061*8975f5c5SAndroid Build Coastguard Worker }
1062*8975f5c5SAndroid Build Coastguard Worker 
1063*8975f5c5SAndroid Build Coastguard Worker #ifdef CEVAL_CXX
ceval_result(std::string expr)1064*8975f5c5SAndroid Build Coastguard Worker     double ceval_result(std::string expr) {
1065*8975f5c5SAndroid Build Coastguard Worker         return ceval_result((char * ) expr.c_str());
1066*8975f5c5SAndroid Build Coastguard Worker     }
ceval_tree(std::string expr)1067*8975f5c5SAndroid Build Coastguard Worker     void ceval_tree(std::string expr) {
1068*8975f5c5SAndroid Build Coastguard Worker         ceval_tree((char * ) expr.c_str());
1069*8975f5c5SAndroid Build Coastguard Worker     }
1070*8975f5c5SAndroid Build Coastguard Worker #endif
1071*8975f5c5SAndroid Build Coastguard Worker /***************************************** !MAIN FUNCTIONS *******************************************/
1072*8975f5c5SAndroid Build Coastguard Worker #endif
1073