UNPKG

algebrite

Version:

Computer Algebra System in Coffeescript

168 lines (141 loc) 2.76 kB
# If the number of args is odd then the last arg is the default result. Eval_test = -> p1 = cdr(p1) while (iscons(p1)) if (cdr(p1) == symbol(NIL)) push(car(p1)); # default case Eval() return push(car(p1)) Eval_predicate() p2 = pop() if (!iszero(p2)) push(cadr(p1)) Eval() return p1 = cddr(p1) push_integer(0) # The test for equality is weaker than the other relational operators. # For example, A<=B causes a stop when the result of A minus B is not a # numerical value. # However, A==B never causes a stop. # For A==B, any nonzero result for A minus B indicates inequality. Eval_testeq = -> # first try without simplifyng both sides push(cadr(p1)) Eval() push(caddr(p1)) Eval() subtract() subtractionResult = pop() if (iszero(subtractionResult)) p1 = subtractionResult push_integer(1) else # they don't seem equal but # let's try again after doing # a simplification on both sides push(cadr(p1)) Eval() simplify() push(caddr(p1)) Eval() simplify() subtract() p1 = pop() if (iszero(p1)) push_integer(1) else push_integer(0) # Relational operators expect a numeric result for operand difference. Eval_testge = -> if (cmp_args() >= 0) push_integer(1) else push_integer(0) Eval_testgt = -> if (cmp_args() > 0) push_integer(1) else push_integer(0) Eval_testle = -> if (cmp_args() <= 0) push_integer(1) else push_integer(0) Eval_testlt = -> if (cmp_args() < 0) push_integer(1) else push_integer(0) # not definition Eval_not = -> push(cadr(p1)) Eval_predicate() p1 = pop() if (iszero(p1)) push_integer(1) else push_integer(0) # and definition Eval_and = -> p1 = cdr(p1) while (iscons(p1)) push(car(p1)) Eval_predicate() p2 = pop() if (iszero(p2)) push_integer(0) return p1 = cdr(p1) push_integer(1) # or definition Eval_or = -> p1 = cdr(p1) while (iscons(p1)) push(car(p1)) Eval_predicate() p2 = pop() if (!iszero(p2)) push_integer(1) return p1 = cdr(p1) push_integer(0) # use subtract for cases like A < A + 1 # TODO you could be smarter here and # simplify both sides only in the case # of "relational operator: cannot determine..." # a bit like we do in Eval_testeq cmp_args = -> t = 0 push(cadr(p1)) Eval() simplify() push(caddr(p1)) Eval() simplify() subtract() p1 = pop() # try floating point if necessary if (p1.k != NUM && p1.k != DOUBLE) push(p1) yyfloat() Eval() p1 = pop() if (iszero(p1)) return 0 switch (p1.k) when NUM if (MSIGN(p1.q.a) == -1) t = -1 else t = 1 when DOUBLE if (p1.d < 0.0) t = -1 else t = 1 else stop("relational operator: cannot determine due to non-numerical comparison of " + p1) t = 0 return t