algebrite
Version:
Computer Algebra System in Coffeescript
232 lines (181 loc) • 2.98 kB
text/coffeescript
# Greatest common denominator
Eval_gcd = ->
p1 = cdr(p1)
push(car(p1))
Eval()
p1 = cdr(p1)
while (iscons(p1))
push(car(p1))
Eval()
gcd()
p1 = cdr(p1)
gcd = ->
prev_expanding = expanding
save()
gcd_main()
restore()
expanding = prev_expanding
gcd_main = ->
expanding = 1
p2 = pop()
p1 = pop()
if (equal(p1, p2))
push(p1)
return
if (isrational(p1) && isrational(p2))
push(p1)
push(p2)
gcd_numbers()
return
if (car(p1) == symbol(ADD) && car(p2) == symbol(ADD))
gcd_expr_expr()
return
if (car(p1) == symbol(ADD))
gcd_expr(p1)
p1 = pop()
if (car(p2) == symbol(ADD))
gcd_expr(p2)
p2 = pop()
if (car(p1) == symbol(MULTIPLY) && car(p2) == symbol(MULTIPLY))
gcd_term_term()
return
if (car(p1) == symbol(MULTIPLY))
gcd_term_factor()
return
if (car(p2) == symbol(MULTIPLY))
gcd_factor_term()
return
# gcd of factors
if (car(p1) == symbol(POWER))
p3 = caddr(p1)
p1 = cadr(p1)
else
p3 = one
if (car(p2) == symbol(POWER))
p4 = caddr(p2)
p2 = cadr(p2)
else
p4 = one
if (!equal(p1, p2))
push(one)
return
# are both exponents numerical?
if (isnum(p3) && isnum(p4))
push(p1)
if (lessp(p3, p4))
push(p3)
else
push(p4)
power()
return
# are the exponents multiples of eah other?
push(p3)
push(p4)
divide()
p5 = pop()
if (isnum(p5))
push(p1)
# choose the smallest exponent
if (car(p3) == symbol(MULTIPLY) && isnum(cadr(p3)))
p5 = cadr(p3)
else
p5 = one
if (car(p4) == symbol(MULTIPLY) && isnum(cadr(p4)))
p6 = cadr(p4)
else
p6 = one
if (lessp(p5, p6))
push(p3)
else
push(p4)
power()
return
push(p3)
push(p4)
subtract()
p5 = pop()
if (!isnum(p5))
push(one)
return
# can't be equal because of test near beginning
push(p1)
if (isnegativenumber(p5))
push(p3)
else
push(p4)
power()
# in this case gcd is used as a composite function, i.e. gcd(gcd(gcd...
gcd_expr_expr = ->
if (length(p1) != length(p2))
push(one)
return
p3 = cdr(p1)
push(car(p3))
p3 = cdr(p3)
while (iscons(p3))
push(car(p3))
gcd()
p3 = cdr(p3)
p3 = pop()
p4 = cdr(p2)
push(car(p4))
p4 = cdr(p4)
while (iscons(p4))
push(car(p4))
gcd()
p4 = cdr(p4)
p4 = pop()
push(p1)
push(p3)
divide()
p5 = pop()
push(p2)
push(p4)
divide()
p6 = pop()
if (equal(p5, p6))
push(p5)
push(p3)
push(p4)
gcd()
multiply()
else
push(one)
gcd_expr = (p) ->
p = cdr(p)
push(car(p))
p = cdr(p)
while (iscons(p))
push(car(p))
gcd()
p = cdr(p)
gcd_term_term = ->
push(one)
p3 = cdr(p1)
while (iscons(p3))
p4 = cdr(p2)
while (iscons(p4))
push(car(p3))
push(car(p4))
gcd()
multiply()
p4 = cdr(p4)
p3 = cdr(p3)
gcd_term_factor = ->
push(one)
p3 = cdr(p1)
while (iscons(p3))
push(car(p3))
push(p2)
gcd()
multiply()
p3 = cdr(p3)
gcd_factor_term = ->
push(one)
p4 = cdr(p2)
while (iscons(p4))
push(p1)
push(car(p4))
gcd()
multiply()
p4 = cdr(p4)