algebrite
Version:
Computer Algebra System in Coffeescript
168 lines (132 loc) • 2.38 kB
text/coffeescript
factorial = ->
n = 0
save()
p1 = pop()
push(p1)
n = pop_integer()
if (n < 0 || n == 0x80000000)
push_symbol(FACTORIAL)
push(p1)
list(2)
restore()
return
bignum_factorial(n)
restore()
simplifyfactorials = ->
x = 0
save()
x = expanding
expanding = 0
p1 = pop()
if (car(p1) == symbol(ADD))
push(zero)
p1 = cdr(p1)
while (iscons(p1))
push(car(p1))
simplifyfactorials()
add()
p1 = cdr(p1)
expanding = x
restore()
return
if (car(p1) == symbol(MULTIPLY))
sfac_product()
expanding = x
restore()
return
push(p1)
expanding = x
restore()
sfac_product = ->
i = 0
j = 0
n = 0
s = tos
p1 = cdr(p1)
n = 0
while (iscons(p1))
push(car(p1))
p1 = cdr(p1)
n++
for i in [0...(n - 1)]
if (stack[s + i] == symbol(NIL))
continue
for j in [(i + 1)...n]
if (stack[s + j] == symbol(NIL))
continue
sfac_product_f(s, i, j)
push(one)
for i in [0...n]
if (stack[s+i] == symbol(NIL))
continue
push(stack[s+i])
multiply()
p1 = pop()
tos -= n
push(p1)
sfac_product_f = (s,a,b) ->
i = 0
n = 0
p1 = stack[s + a]
p2 = stack[s + b]
if (ispower(p1))
p3 = caddr(p1)
p1 = cadr(p1)
else
p3 = one
if (ispower(p2))
p4 = caddr(p2)
p2 = cadr(p2)
else
p4 = one
if (isfactorial(p1) && isfactorial(p2))
# Determine if the powers cancel.
push(p3)
push(p4)
add()
yyexpand()
n = pop_integer()
if (n != 0)
return
push(cadr(p1))
push(cadr(p2))
subtract()
yyexpand();
n = pop_integer()
if (n == 0 || n == 0x80000000)
return
if (n < 0)
n = -n
p5 = p1
p1 = p2
p2 = p5
p5 = p3
p3 = p4
p4 = p5
push(one)
for i in [1..n]
push(cadr(p2))
push_integer(i)
add()
push(p3)
power()
multiply()
stack[s+a] = pop()
stack[s+b] = symbol(NIL)