/* evalf3.c (yukino.c) - Don Yang (uguu.org) Preprocess step 3: optimize code. 11/05/99 */ #include #include #include #define isdigit0(x) (x > 47 && x < 58) || x == 46 char *label[19] = { "-", "+", "%", "/", "*", "-", "exp", "ln", "log", "atan", "acos", "asin", "tan", "cos", "sin", "^", "(", "e", "PI"}, expression[2049]; int expindex, lasttoken, lastop, nestlevel, operator[2048], left[2048], right[2048], parent[2048], newnode, cursor, i; double operand[2048], lit; double evaluate(int node) { switch( operator[node] ) { case 294: return atan2(0, -1); case 278: return exp(1); case 262: return evaluate(right[node]); case 245: return pow(evaluate(left[node]), evaluate(right[node])); case 228: return sin(evaluate(right[node])); case 212: return cos(evaluate(right[node])); case 196: return tan(evaluate(right[node])); case 180: return asin(evaluate(right[node])); case 164: return acos(evaluate(right[node])); case 148: return atan(evaluate(right[node])); case 132: return log10(evaluate(right[node])); case 116: return log(evaluate(right[node])); case 100: return exp(evaluate(right[node])); case 83: return -evaluate(right[node]); case 66: return evaluate(left[node]) * evaluate(right[node]); case 50: return evaluate(left[node]) / evaluate(right[node]); case 34: return fmod(evaluate(left[node]), evaluate(right[node])); case 17: return evaluate(left[node]) + evaluate(right[node]); case 1: return evaluate(left[node]) - evaluate(right[node]); } return operand[node]; } void insertbop(int op) { for(lasttoken = lastop = !printf("%s ", label[op >> 4]); operator[parent[cursor]] - 262 && (operator[parent[cursor]] & 7) >= (op & 7); cursor = parent[cursor]); parent[newnode] = parent[left[newnode] = cursor]; operator[parent[cursor] = right[parent[newnode]] = newnode] = op; cursor = newnode++; } void insertuop(int op) { if( lasttoken ) insertbop(66); if( op == 310 ) { lasttoken = printf("%lG ", operand[newnode] = lit); } else if( op == 294 || op == 278 ) { lasttoken = printf("%s ", label[op >> 4]); } else { if( op == 262 ) { nestlevel++; if( lastop ) putchar(8); } lasttoken = !printf("%s", label[op >> 4]); } lastop = 0; if( op > 99 && op < 229 ) lastop = putchar(32); operator[newnode] = op; parent[right[cursor] = newnode] = cursor; cursor = newnode++; } int main(int argc, char *argv[]) { if( argc == 1 ) return puts("?"); strcpy(expression, argv[newnode = 1]); for(i = 2; i < argc; strcat(expression, argv[i++])); strlwr(expression); for(operator[expindex = lasttoken = nestlevel = cursor = 0] = 262; expression[expindex];) { if( isdigit0(expression[expindex]) ) { sscanf(expression + expindex, "%lf", &lit); for(insertuop(310); isdigit0(expression[expindex]); expindex++); if( expression[expindex] == 101 ) { expindex++; if( expression[expindex] - 43 && expression[expindex] - 45 ) expindex--; for(expindex++; expression[expindex] > 47 && expression[expindex] < 58; expindex++); } } else if( expression[expindex] > 97 && expression[expindex] < 117 ) { if( !memcmp(expression + expindex, label[14], 3) ) insertuop(228); else if( !memcmp(expression + expindex, label[13], 3) ) insertuop(212); else if( !memcmp(expression + expindex, label[12], 3) ) insertuop(196); else if( !memcmp(expression + expindex, label[6], 3) ) insertuop(100); else if( !memcmp(expression + expindex, label[8], 3) ) insertuop(132); else { if( !memcmp(expression + expindex, "pi", 2) ) insertuop(294); else if( !memcmp(expression + expindex, "ln", 2) ) insertuop(116); else { if( expression[expindex] == 101 ) insertuop(278); expindex--; } expindex--; } expindex += 3; } else if( expression[expindex] == 97 ) { expindex++; if( !memcmp(expression + expindex, label[14], 3) ) insertuop(180); else if( !memcmp(expression + expindex, label[13], 3) ) insertuop(164); else if( !memcmp(expression + expindex, label[12], 3) ) insertuop(148); else expindex -= 3; expindex += 3; } else { i = expression[expindex++]; if( lasttoken ) { if( i == 40 ) { insertuop(262); } else if( i == 41 && nestlevel ) { printf("\b) "); for(cursor = parent[cursor]; operator[cursor] - 262; cursor = parent[cursor]); nestlevel--; } else { if( i == 42 ) insertbop(66); else if( i == 47 ) insertbop(50); else if( i == 37 ) insertbop(34); else if( i == 43 ) insertbop(17); else if( i == 45 ) insertbop(1); else if( i == 94 ) insertbop(245); } } else { if( i == 40 ) insertuop(262); else if( i == 45 ) insertuop(83); } } } if( !lasttoken ) { lit = 0; insertuop(310); } for(i = !putchar(8); i++ < nestlevel; putchar(41)); return !printf("\n= %.16lG\n", evaluate(0)); }