algebrite
Version:
Computer Algebra System in Coffeescript
237 lines (190 loc) • 3.52 kB
text/coffeescript
#-----------------------------------------------------------------------------
#
# Generate all divisors of a term
#
# Input: Term on stack (factor * factor * ...)
#
# Output: Divisors on stack
#
#-----------------------------------------------------------------------------
divisors = ->
i = 0
h = 0
n = 0
save()
h = tos - 1
divisors_onstack()
n = tos - h
#qsort(stack + h, n, sizeof (U *), __cmp)
subsetOfStack = stack.slice(h,h+n)
subsetOfStack.sort(cmp_expr)
stack = stack.slice(0,h).concat(subsetOfStack).concat(stack.slice(h+n))
p1 = alloc_tensor(n)
p1.tensor.ndim = 1
p1.tensor.dim[0] = n
for i in [0...n]
p1.tensor.elem[i] = stack[h + i]
moveTos h
push(p1)
restore()
divisors_onstack = ->
h = 0
i = 0
k = 0
n = 0
save()
p1 = pop()
h = tos
# push all of the term's factors
if (isnum(p1))
push(p1)
factor_small_number()
else if (car(p1) == symbol(ADD))
push(p1)
__factor_add()
#printf(">>>\n")
#for (i = h; i < tos; i++)
#print(stdout, stack[i])
#printf("<<<\n")
else if (car(p1) == symbol(MULTIPLY))
p1 = cdr(p1)
if (isnum(car(p1)))
push(car(p1))
factor_small_number()
p1 = cdr(p1)
while (iscons(p1))
p2 = car(p1)
if (car(p2) == symbol(POWER))
push(cadr(p2))
push(caddr(p2))
else
push(p2)
push(one)
p1 = cdr(p1)
else if (car(p1) == symbol(POWER))
push(cadr(p1))
push(caddr(p1))
else
push(p1)
push(one)
k = tos
# contruct divisors by recursive descent
push(one)
gen(h, k)
# move
n = tos - k
for i in [0...n]
stack[h + i] = stack[k + i]
moveTos h + n
restore()
#-----------------------------------------------------------------------------
#
# Generate divisors
#
# Input: Base-exponent pairs on stack
#
# h first pair
#
# k just past last pair
#
# Output: Divisors on stack
#
# For example, factor list 2 2 3 1 results in 6 divisors,
#
# 1
# 3
# 2
# 6
# 4
# 12
#
#-----------------------------------------------------------------------------
#define ACCUM p1
#define BASE p2
#define EXPO p3
gen = (h,k) ->
expo = 0
i = 0
save()
p1 = pop()
if (h == k)
push(p1)
restore()
return
p2 = stack[h + 0]
p3 = stack[h + 1]
push(p3)
expo = pop_integer()
if (!isNaN(expo))
for i in [0..Math.abs(expo)]
push(p1)
push(p2)
push_integer(sign(expo) * i)
power()
multiply()
gen(h + 2, k)
restore()
#-----------------------------------------------------------------------------
#
# Factor ADD expression
#
# Input: Expression on stack
#
# Output: Factors on stack
#
# Each factor consists of two expressions, the factor itself followed
# by the exponent.
#
#-----------------------------------------------------------------------------
__factor_add = ->
save()
p1 = pop()
# get gcd of all terms
p3 = cdr(p1)
push(car(p3))
p3 = cdr(p3)
while (iscons(p3))
push(car(p3))
gcd()
p3 = cdr(p3)
# check gcd
p2 = pop()
if (isplusone(p2))
push(p1)
push(one)
restore()
return
# push factored gcd
if (isnum(p2))
push(p2)
factor_small_number()
else if (car(p2) == symbol(MULTIPLY))
p3 = cdr(p2)
if (isnum(car(p3)))
push(car(p3))
factor_small_number()
else
push(car(p3))
push(one)
p3 = cdr(p3)
while (iscons(p3))
push(car(p3))
push(one)
p3 = cdr(p3)
else
push(p2)
push(one)
# divide each term by gcd
push(p2)
inverse()
p2 = pop()
push(zero)
p3 = cdr(p1)
while (iscons(p3))
push(p2)
push(car(p3))
multiply()
add()
p3 = cdr(p3)
push(one)
restore()