Status apply_operator(const Operator *operator, Stack **operands) { if (!operator || !*operands) { return ERROR_SYNTAX; } if (operator->arity == OPERATOR_UNARY) { return apply_unary_operator(operator, operands); } double y = pop_double(operands); if (!*operands) { return ERROR_SYNTAX; } double x = pop_double(operands); Status status = OK; switch (operator->symbol) { case '^': x = pow(x, y); break; case '*': x = x * y; break; case '/': x = x / y; break; case '%': x = fmod(x, y); break; case '+': x = x + y; break; case '-': x = x - y; break; default: return ERROR_UNRECOGNIZED; } push_double(x, operands); return status; }
void setup_yrange_f(void) { // default range is (-10,10) ymin = -10.0; ymax = 10.0; p1 = usr_symbol("yrange"); if (!issymbol(p1)) return; p1 = get_binding(p1); // must be two element vector if (!istensor(p1) || p1->u.tensor->ndim != 1 || p1->u.tensor->nelem != 2) return; push(p1->u.tensor->elem[0]); eval(); yyfloat(); eval(); p2 = pop(); push(p1->u.tensor->elem[1]); eval(); yyfloat(); eval(); p3 = pop(); if (!isnum(p2) || !isnum(p3)) return; push(p2); ymin = pop_double(); push(p3); ymax = pop_double(); if (ymin == ymax) stop("draw: yrange is zero"); }
void setup_trange_f(void) { // default range is (-pi, pi) tmin = -M_PI; tmax = M_PI; p1 = usr_symbol("trange"); if (!issymbol(p1)) return; p1 = get_binding(p1); // must be two element vector if (!istensor(p1) || p1->u.tensor->ndim != 1 || p1->u.tensor->nelem != 2) return; push(p1->u.tensor->elem[0]); eval(); yyfloat(); eval(); p2 = pop(); push(p1->u.tensor->elem[1]); eval(); yyfloat(); eval(); p3 = pop(); if (!isnum(p2) || !isnum(p3)) return; push(p2); tmin = pop_double(); push(p3); tmax = pop_double(); if (tmin == tmax) stop("draw: trange is zero"); }
void new_point(double t) { double x, y; if (draw_count >= YMAX) return; draw_buf[draw_count].x = -10000; draw_buf[draw_count].y = -10000; draw_buf[draw_count].t = t; draw_count++; get_xy(t); if (!isnum(XT) || !isnum(YT)) return; push(XT); x = pop_double(); x = (x - xmin) / (xmax - xmin); x = (double) DIMX * x + 0.5; // map 0-1 to 0-DIM, +0.5 so draw(x^3) looks right push(YT); y = pop_double(); y = (y - ymin) / (ymax - ymin); y = (double) DIMY * y + 0.5; // map 0-1 to 0-DIM, +0.5 so draw(x^3) looks right if (x < -10000.0) x = -10000.0; if (x > 10000.0) x = 10000.0; if (y < -10000.0) y = -10000.0; if (y > 10000.0) y = 10000.0; draw_buf[draw_count - 1].x = (int) x; draw_buf[draw_count - 1].y = (int) y; }
Status shunting_yard(const char *expression, double *result) { Token *tokens = tokenize(expression); Stack *operands = NULL, *operators = NULL, *functions = NULL; Status status = parse(tokens, &operands, &operators, &functions); if (operands) { *result = round(pop_double(&operands) * 10e14) / 10e14; } else if (status == OK) { status = ERROR_NO_INPUT; } Token *token; for (token = tokens; token->type != TOKEN_NONE; token++) { free(token->value); } free(tokens); while (operands) { pop_double(&operands); } while (operators) { stack_pop(&operators); } while (functions) { stack_pop(&functions); } return status; }
Status apply_function(const char *function, Stack **operands) { if (!*operands) { return ERROR_FUNCTION_ARGUMENTS; } double x = pop_double(operands); if (strcasecmp(function, "abs") == 0) { x = fabs(x); } else if (strcasecmp(function, "sqrt") == 0) { x = sqrt(x); } else if (strcasecmp(function, "ln") == 0) { x = log(x); } else if (strcasecmp(function, "lb") == 0) { x = log2(x); } else if (strcasecmp(function, "lg") == 0 || strcasecmp(function, "log") == 0) { x = log10(x); } else if (strcasecmp(function, "cos") == 0) { x = cos(x); } else if (strcasecmp(function, "sin") == 0) { x = sin(x); } else if (strcasecmp(function, "tan") == 0) { x = tan(x); } else { return ERROR_UNDEFINED_FUNCTION; } push_double(x, operands); return OK; }
Status apply_unary_operator(const Operator *operator, Stack **operands) { double x = pop_double(operands); switch (operator->symbol) { case '+': break; case '-': x = -x; break; case '!': x = tgamma(x + 1); break; default: return ERROR_UNRECOGNIZED; } push_double(x, operands); return OK; }
void NativeGenerator::generate_native_math_entries() { comment_section("Native entry points for math functions"); int offset = 0; #if ENABLE_FLOAT stop_code_segment(); start_data_segment(); stop_data_segment(); start_code_segment(); // Generate sinus entry. offset = 0; rom_linkable_entry("native_math_sin_entry"); comment("store return address"); popl(edi); pop_double(eax, ecx); pushl(ecx); pushl(eax); call(Constant("jvm_sin")); addl(esp, Constant(8)); push_from_fpu_stack(double_tag, offset, true); jmp(edi); rom_linkable_entry_end(); // native_math_sin_entry // Generate cosinus entry. offset = 0; rom_linkable_entry("native_math_cos_entry"); comment("store return address"); popl(edi); pop_double(eax, ecx); pushl(ecx); pushl(eax); call(Constant("jvm_cos")); addl(esp, Constant(8)); push_from_fpu_stack(double_tag, offset, true); jmp(edi); rom_linkable_entry_end(); // native_math_cos_entry // Generate tangent entry. offset = 0; rom_linkable_entry("native_math_tan_entry"); comment("store return address"); popl(edi); pop_double(eax, ecx); pushl(ecx); pushl(eax); call(Constant("jvm_tan")); addl(esp, Constant(8)); push_from_fpu_stack(double_tag, offset, true); jmp(edi); rom_linkable_entry_end(); // native_math_tan_entry // Generate square root entry. offset = 0; rom_linkable_entry("native_math_sqrt_entry"); comment("store return address"); popl(edi); pop_double(eax, ecx); pushl(ecx); pushl(eax); call(Constant("jvm_sqrt")); addl(esp, Constant(8)); push_from_fpu_stack(double_tag, offset, true); jmp(edi); rom_linkable_entry_end(); // native_math_sqrt_entry // Generate ceil entry. offset = 0; rom_linkable_entry("native_math_ceil_entry"); comment("store return address"); popl(edi); pop_double(eax, ecx); pushl(ecx); pushl(eax); call(Constant("jvm_ceil")); addl(esp, Constant(8)); push_from_fpu_stack(double_tag, offset, true); jmp(edi); rom_linkable_entry_end(); // native_math_ceil_entry // Generate floor entry. offset = 0; rom_linkable_entry("native_math_floor_entry"); comment("store return address"); popl(edi); pop_double(eax, ecx); pushl(ecx); pushl(eax); call(Constant("jvm_floor")); addl(esp, Constant(8)); push_from_fpu_stack(double_tag, offset, true); jmp(edi); rom_linkable_entry_end(); // native_math_floor_entry #endif /* ENABLE_FLOAT */ }