200 lines
3.5 KiB
CoffeeScript
200 lines
3.5 KiB
CoffeeScript
|
|
|
|
# s is a string
|
|
new_string = (s) ->
|
|
theNewString = new U()
|
|
theNewString.k = STR
|
|
theNewString.str = s
|
|
return theNewString
|
|
|
|
out_of_memory = ->
|
|
stop("out of memory")
|
|
|
|
# both ints
|
|
push_zero_matrix = (i,j) ->
|
|
push(alloc_tensor(i * j))
|
|
stack[tos - 1].tensor.ndim = 2
|
|
stack[tos - 1].tensor.dim[0] = i
|
|
stack[tos - 1].tensor.dim[1] = j
|
|
|
|
push_identity_matrix = (n) ->
|
|
push_zero_matrix(n, n)
|
|
for i in [0...n]
|
|
stack[tos - 1].tensor.elem[i * n + i] = one
|
|
|
|
check_tensor_dimensions stack[tos - 1]
|
|
|
|
push_cars = (p) ->
|
|
while (iscons(p))
|
|
push(car(p))
|
|
p = cdr(p)
|
|
|
|
# see cmp_expr definition, this
|
|
# function alone just does simple structure comparison
|
|
# or compares numbers (either rationals or integers or doubles)
|
|
# but can't be used alone to test
|
|
# more complex mathematical equalities...
|
|
equal = (p1,p2) ->
|
|
if (cmp_expr(p1, p2) == 0)
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
lessp = (p1,p2) ->
|
|
if (cmp_expr(p1, p2) < 0)
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
sign = (n) ->
|
|
if (n < 0)
|
|
return -1
|
|
else if (n > 0)
|
|
return 1
|
|
else
|
|
return 0
|
|
|
|
# compares whether two expressions
|
|
# have the same structure.
|
|
# For example this method alone
|
|
# would compare "1+1" and "2"
|
|
# as different.
|
|
# It just so happens though that one oftens
|
|
# evaluates the two sides before passing them
|
|
# to this function, so chances are that the two
|
|
# sides have the same normal form.
|
|
# Even a simple evaluation might not cut it
|
|
# though... a simplification of both sides
|
|
# would then help. And even that might not
|
|
# cut it in some cases...
|
|
cmp_expr = (p1, p2) ->
|
|
n = 0
|
|
|
|
if (p1 == p2)
|
|
return 0
|
|
|
|
if (p1 == symbol(NIL))
|
|
return -1
|
|
|
|
if (p2 == symbol(NIL))
|
|
return 1
|
|
|
|
if (isNumericAtom(p1) && isNumericAtom(p2))
|
|
return sign(compare_numbers(p1, p2))
|
|
|
|
if (isNumericAtom(p1))
|
|
return -1
|
|
|
|
if (isNumericAtom(p2))
|
|
return 1
|
|
|
|
if (isstr(p1) && isstr(p2))
|
|
return sign(strcmp(p1.str,p2.str))
|
|
|
|
if (isstr(p1))
|
|
return -1
|
|
|
|
if (isstr(p2))
|
|
return 1
|
|
|
|
if (issymbol(p1) && issymbol(p2))
|
|
return sign(strcmp(get_printname(p1),get_printname(p2)))
|
|
|
|
if (issymbol(p1))
|
|
return -1
|
|
|
|
if (issymbol(p2))
|
|
return 1
|
|
|
|
if (istensor(p1) && istensor(p2))
|
|
return compare_tensors(p1, p2)
|
|
|
|
if (istensor(p1))
|
|
return -1
|
|
|
|
if (istensor(p2))
|
|
return 1
|
|
|
|
# recursion here
|
|
while (iscons(p1) && iscons(p2))
|
|
n = cmp_expr(car(p1), car(p2))
|
|
if (n != 0)
|
|
return n
|
|
p1 = cdr(p1)
|
|
p2 = cdr(p2)
|
|
|
|
if (iscons(p2))
|
|
return -1
|
|
|
|
if (iscons(p1))
|
|
return 1
|
|
|
|
return 0
|
|
|
|
length = (p) ->
|
|
n = 0
|
|
while (iscons(p))
|
|
p = cdr(p)
|
|
n++
|
|
return n
|
|
|
|
unique = (p) ->
|
|
save()
|
|
p1 = symbol(NIL)
|
|
p2 = symbol(NIL)
|
|
unique_f(p)
|
|
if (p2 != symbol(NIL))
|
|
p1 = symbol(NIL)
|
|
p = p1
|
|
restore()
|
|
return p
|
|
|
|
unique_f = (p) ->
|
|
if (isstr(p))
|
|
if (p1 == symbol(NIL))
|
|
p1 = p
|
|
else if (p != p1)
|
|
p2 = p
|
|
return
|
|
while (iscons(p))
|
|
unique_f(car(p))
|
|
if (p2 != symbol(NIL))
|
|
return
|
|
p = cdr(p)
|
|
|
|
|
|
ssqrt = ->
|
|
push_rational(1, 2)
|
|
power()
|
|
|
|
yyexpand = ->
|
|
prev_expanding = expanding
|
|
expanding = 1
|
|
Eval()
|
|
expanding = prev_expanding
|
|
|
|
exponential = ->
|
|
push_symbol(E)
|
|
swap()
|
|
power()
|
|
|
|
square = ->
|
|
push_integer(2)
|
|
power()
|
|
|
|
#__cmp = (p1, p2) ->
|
|
# return cmp_expr(p1, p2)
|
|
|
|
# n an integer
|
|
sort_stack = (n) ->
|
|
#qsort(stack + tos - n, n, sizeof (U *), __cmp)
|
|
|
|
h = tos - n
|
|
subsetOfStack = stack.slice(h,h+n)
|
|
subsetOfStack.sort(cmp_expr)
|
|
stack = stack.slice(0,h).concat(subsetOfStack).concat(stack.slice(h+n))
|
|
|
|
|
|
$.equal = equal
|
|
$.length = length
|