685 lines
10 KiB
CoffeeScript
685 lines
10 KiB
CoffeeScript
# derivative
|
|
|
|
|
|
|
|
#define F p3
|
|
#define X p4
|
|
#define N p5
|
|
|
|
Eval_derivative = ->
|
|
|
|
# evaluate 1st arg to get function F
|
|
|
|
i = 0
|
|
p1 = cdr(p1)
|
|
push(car(p1))
|
|
Eval()
|
|
|
|
# evaluate 2nd arg and then...
|
|
|
|
# example result of 2nd arg what to do
|
|
#
|
|
# d(f) nil guess X, N = nil
|
|
# d(f,2) 2 guess X, N = 2
|
|
# d(f,x) x X = x, N = nil
|
|
# d(f,x,2) x X = x, N = 2
|
|
# d(f,x,y) x X = x, N = y
|
|
|
|
p1 = cdr(p1)
|
|
push(car(p1))
|
|
Eval()
|
|
|
|
p2 = pop()
|
|
if (p2 == symbol(NIL))
|
|
guess()
|
|
push(symbol(NIL))
|
|
else if (isNumericAtom(p2))
|
|
guess()
|
|
push(p2)
|
|
else
|
|
push(p2)
|
|
p1 = cdr(p1)
|
|
push(car(p1))
|
|
Eval()
|
|
|
|
p5 = pop(); # p5 is N
|
|
p4 = pop(); # p4 is X
|
|
p3 = pop(); # p3 is F
|
|
|
|
while (1)
|
|
|
|
# p5 (N) might be a symbol instead of a number
|
|
|
|
if (isNumericAtom(p5)) # p5 is N
|
|
push(p5); # p5 is N
|
|
n = pop_integer()
|
|
if (isNaN(n))
|
|
stop("nth derivative: check n")
|
|
else
|
|
n = 1
|
|
|
|
push(p3); # p3 is F
|
|
|
|
if (n >= 0)
|
|
for i in [0...n]
|
|
push(p4); # p4 is X
|
|
derivative()
|
|
else
|
|
n = -n
|
|
for i in [0...n]
|
|
push(p4); # p4 is X
|
|
integral()
|
|
|
|
p3 = pop(); # p3 is F
|
|
|
|
# if p5 (N) is nil then arglist is exhausted
|
|
|
|
if (p5 == symbol(NIL)) # p5 is N
|
|
break
|
|
|
|
# otherwise...
|
|
|
|
# N arg1 what to do
|
|
#
|
|
# number nil break
|
|
# number number N = arg1, continue
|
|
# number symbol X = arg1, N = arg2, continue
|
|
#
|
|
# symbol nil X = N, N = nil, continue
|
|
# symbol number X = N, N = arg1, continue
|
|
# symbol symbol X = N, N = arg1, continue
|
|
|
|
if (isNumericAtom(p5)) # p5 is N
|
|
p1 = cdr(p1)
|
|
push(car(p1))
|
|
Eval()
|
|
p5 = pop(); # p5 is N
|
|
if (p5 == symbol(NIL)) # p5 is N
|
|
break; # arglist exhausted
|
|
if (isNumericAtom(p5)) # p5 is N
|
|
doNothing = 1 # N = arg1
|
|
else
|
|
p4 = p5; # p5 is N # p4 is X # X = arg1
|
|
p1 = cdr(p1)
|
|
push(car(p1))
|
|
Eval()
|
|
p5 = pop(); # p5 is N # N = arg2
|
|
else
|
|
p4 = p5; # p5 is N # p4 is X # X = N
|
|
p1 = cdr(p1)
|
|
push(car(p1))
|
|
Eval()
|
|
p5 = pop(); # p5 is N # N = arg1
|
|
|
|
push(p3); # p3 is F # final result
|
|
|
|
derivative = ->
|
|
save()
|
|
p2 = pop()
|
|
p1 = pop()
|
|
if (isNumericAtom(p2))
|
|
stop("undefined function")
|
|
if (istensor(p1))
|
|
if (istensor(p2))
|
|
d_tensor_tensor()
|
|
else
|
|
d_tensor_scalar()
|
|
else
|
|
if (istensor(p2))
|
|
d_scalar_tensor()
|
|
else
|
|
d_scalar_scalar()
|
|
restore()
|
|
|
|
d_scalar_scalar = ->
|
|
if (issymbol(p2))
|
|
d_scalar_scalar_1()
|
|
else
|
|
# Example: d(sin(cos(x)),cos(x))
|
|
# Replace cos(x) <- X, find derivative, then do X <- cos(x)
|
|
push(p1); # sin(cos(x))
|
|
push(p2); # cos(x)
|
|
push(symbol(SECRETX)); # X
|
|
subst(); # sin(cos(x)) -> sin(X)
|
|
push(symbol(SECRETX)); # X
|
|
derivative()
|
|
push(symbol(SECRETX)); # X
|
|
push(p2); # cos(x)
|
|
subst(); # cos(X) -> cos(cos(x))
|
|
|
|
d_scalar_scalar_1 = ->
|
|
# d(x,x)?
|
|
|
|
if (equal(p1, p2))
|
|
push(one)
|
|
return
|
|
|
|
# d(a,x)?
|
|
|
|
if (!iscons(p1))
|
|
push(zero)
|
|
return
|
|
|
|
if (isadd(p1))
|
|
dsum()
|
|
return
|
|
|
|
if (car(p1) == symbol(MULTIPLY))
|
|
dproduct()
|
|
return
|
|
|
|
if (car(p1) == symbol(POWER))
|
|
dpower()
|
|
return
|
|
|
|
if (car(p1) == symbol(DERIVATIVE))
|
|
dd()
|
|
return
|
|
|
|
if (car(p1) == symbol(LOG))
|
|
dlog()
|
|
return
|
|
|
|
if (car(p1) == symbol(SIN))
|
|
dsin()
|
|
return
|
|
|
|
if (car(p1) == symbol(COS))
|
|
dcos()
|
|
return
|
|
|
|
if (car(p1) == symbol(TAN))
|
|
dtan()
|
|
return
|
|
|
|
if (car(p1) == symbol(ARCSIN))
|
|
darcsin()
|
|
return
|
|
|
|
if (car(p1) == symbol(ARCCOS))
|
|
darccos()
|
|
return
|
|
|
|
if (car(p1) == symbol(ARCTAN))
|
|
darctan()
|
|
return
|
|
|
|
if (car(p1) == symbol(SINH))
|
|
dsinh()
|
|
return
|
|
|
|
if (car(p1) == symbol(COSH))
|
|
dcosh()
|
|
return
|
|
|
|
if (car(p1) == symbol(TANH))
|
|
dtanh()
|
|
return
|
|
|
|
if (car(p1) == symbol(ARCSINH))
|
|
darcsinh()
|
|
return
|
|
|
|
if (car(p1) == symbol(ARCCOSH))
|
|
darccosh()
|
|
return
|
|
|
|
if (car(p1) == symbol(ARCTANH))
|
|
darctanh()
|
|
return
|
|
|
|
if (car(p1) == symbol(ABS))
|
|
dabs()
|
|
return
|
|
|
|
if (car(p1) == symbol(SGN))
|
|
dsgn()
|
|
return
|
|
|
|
if (car(p1) == symbol(HERMITE))
|
|
dhermite()
|
|
return
|
|
|
|
if (car(p1) == symbol(ERF))
|
|
derf()
|
|
return
|
|
|
|
if (car(p1) == symbol(ERFC))
|
|
derfc()
|
|
return
|
|
|
|
if (car(p1) == symbol(BESSELJ))
|
|
if (isZeroAtomOrTensor(caddr(p1)))
|
|
dbesselj0()
|
|
else
|
|
dbesseljn()
|
|
return
|
|
|
|
if (car(p1) == symbol(BESSELY))
|
|
if (isZeroAtomOrTensor(caddr(p1)))
|
|
dbessely0()
|
|
else
|
|
dbesselyn()
|
|
return
|
|
|
|
if (car(p1) == symbol(INTEGRAL) && caddr(p1) == p2)
|
|
derivative_of_integral()
|
|
return
|
|
|
|
dfunction()
|
|
|
|
dsum = ->
|
|
h = tos
|
|
p1 = cdr(p1)
|
|
while (iscons(p1))
|
|
push(car(p1))
|
|
push(p2)
|
|
derivative()
|
|
p1 = cdr(p1)
|
|
add_all(tos - h)
|
|
|
|
dproduct = ->
|
|
i = 0
|
|
j = 0
|
|
n = 0
|
|
n = length(p1) - 1
|
|
for i in [0...n]
|
|
p3 = cdr(p1)
|
|
for j in [0...n]
|
|
push(car(p3))
|
|
if (i == j)
|
|
push(p2)
|
|
derivative()
|
|
p3 = cdr(p3)
|
|
multiply_all(n)
|
|
add_all(n)
|
|
|
|
#-----------------------------------------------------------------------------
|
|
#
|
|
# v
|
|
# y = u
|
|
#
|
|
# log y = v log u
|
|
#
|
|
# 1 dy v du dv
|
|
# - -- = - -- + (log u) --
|
|
# y dx u dx dx
|
|
#
|
|
# dy v v du dv
|
|
# -- = u (- -- + (log u) --)
|
|
# dx u dx dx
|
|
#
|
|
#-----------------------------------------------------------------------------
|
|
|
|
dpower = ->
|
|
push(caddr(p1)); # v/u
|
|
push(cadr(p1))
|
|
divide()
|
|
|
|
push(cadr(p1)); # du/dx
|
|
push(p2)
|
|
derivative()
|
|
|
|
multiply()
|
|
|
|
push(cadr(p1)); # log u
|
|
logarithm()
|
|
|
|
push(caddr(p1)); # dv/dx
|
|
push(p2)
|
|
derivative()
|
|
|
|
multiply()
|
|
|
|
add()
|
|
|
|
push(p1); # u^v
|
|
|
|
multiply()
|
|
|
|
dlog = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
divide()
|
|
|
|
# derivative of derivative
|
|
#
|
|
# example: d(d(f(x,y),y),x)
|
|
#
|
|
# p1 = d(f(x,y),y)
|
|
#
|
|
# p2 = x
|
|
#
|
|
# cadr(p1) = f(x,y)
|
|
#
|
|
# caddr(p1) = y
|
|
|
|
dd = ->
|
|
# d(f(x,y),x)
|
|
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
|
|
p3 = pop()
|
|
|
|
if (car(p3) == symbol(DERIVATIVE))
|
|
|
|
# sort dx terms
|
|
|
|
push_symbol(DERIVATIVE)
|
|
push_symbol(DERIVATIVE)
|
|
push(cadr(p3))
|
|
|
|
if (lessp(caddr(p3), caddr(p1)))
|
|
push(caddr(p3))
|
|
list(3)
|
|
push(caddr(p1))
|
|
else
|
|
push(caddr(p1))
|
|
list(3)
|
|
push(caddr(p3))
|
|
|
|
list(3)
|
|
|
|
else
|
|
push(p3)
|
|
push(caddr(p1))
|
|
derivative()
|
|
|
|
# derivative of a generic function
|
|
|
|
dfunction = ->
|
|
p3 = cdr(p1); # p3 is the argument list for the function
|
|
|
|
if (p3 == symbol(NIL) || Find(p3, p2))
|
|
push_symbol(DERIVATIVE)
|
|
push(p1)
|
|
push(p2)
|
|
list(3)
|
|
else
|
|
push(zero)
|
|
|
|
dsin = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
cosine()
|
|
multiply()
|
|
|
|
dcos = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
sine()
|
|
multiply()
|
|
negate()
|
|
|
|
dtan = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
cosine()
|
|
push_integer(-2)
|
|
power()
|
|
multiply()
|
|
|
|
darcsin = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push_integer(1)
|
|
push(cadr(p1))
|
|
push_integer(2)
|
|
power()
|
|
subtract()
|
|
push_rational(-1, 2)
|
|
power()
|
|
multiply()
|
|
|
|
darccos = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push_integer(1)
|
|
push(cadr(p1))
|
|
push_integer(2)
|
|
power()
|
|
subtract()
|
|
push_rational(-1, 2)
|
|
power()
|
|
multiply()
|
|
negate()
|
|
|
|
# Without simplify With simplify
|
|
#
|
|
# d(arctan(y/x),x) -y/(x^2*(y^2/x^2+1)) -y/(x^2+y^2)
|
|
#
|
|
# d(arctan(y/x),y) 1/(x*(y^2/x^2+1)) x/(x^2+y^2)
|
|
|
|
darctan = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push_integer(1)
|
|
push(cadr(p1))
|
|
push_integer(2)
|
|
power()
|
|
add()
|
|
inverse()
|
|
multiply()
|
|
simplify()
|
|
|
|
dsinh = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
ycosh()
|
|
multiply()
|
|
|
|
dcosh = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
ysinh()
|
|
multiply()
|
|
|
|
dtanh = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
ycosh()
|
|
push_integer(-2)
|
|
power()
|
|
multiply()
|
|
|
|
darcsinh = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
push_integer(2)
|
|
power()
|
|
push_integer(1)
|
|
add()
|
|
push_rational(-1, 2)
|
|
power()
|
|
multiply()
|
|
|
|
darccosh = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
push_integer(2)
|
|
power()
|
|
push_integer(-1)
|
|
add()
|
|
push_rational(-1, 2)
|
|
power()
|
|
multiply()
|
|
|
|
darctanh = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push_integer(1)
|
|
push(cadr(p1))
|
|
push_integer(2)
|
|
power()
|
|
subtract()
|
|
inverse()
|
|
multiply()
|
|
|
|
dabs = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
sgn()
|
|
multiply()
|
|
|
|
dsgn = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
dirac()
|
|
multiply()
|
|
push_integer(2)
|
|
multiply()
|
|
|
|
dhermite = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push_integer(2)
|
|
push(caddr(p1))
|
|
multiply()
|
|
multiply()
|
|
push(cadr(p1))
|
|
push(caddr(p1))
|
|
push_integer(-1)
|
|
add()
|
|
hermite()
|
|
multiply()
|
|
|
|
derf = ->
|
|
push(cadr(p1))
|
|
push_integer(2)
|
|
power()
|
|
push_integer(-1)
|
|
multiply()
|
|
exponential()
|
|
if evaluatingAsFloats
|
|
push_double(Math.PI)
|
|
else
|
|
push_symbol(PI)
|
|
push_rational(-1,2)
|
|
power()
|
|
multiply()
|
|
push_integer(2)
|
|
multiply()
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
multiply()
|
|
|
|
derfc = ->
|
|
push(cadr(p1))
|
|
push_integer(2)
|
|
power()
|
|
push_integer(-1)
|
|
multiply()
|
|
exponential()
|
|
if evaluatingAsFloats
|
|
push_double(Math.PI)
|
|
else
|
|
push_symbol(PI)
|
|
push_rational(-1,2)
|
|
power()
|
|
multiply()
|
|
push_integer(-2)
|
|
multiply()
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
multiply()
|
|
|
|
dbesselj0 = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
push_integer(1)
|
|
besselj()
|
|
multiply()
|
|
push_integer(-1)
|
|
multiply()
|
|
|
|
dbesseljn = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
push(caddr(p1))
|
|
push_integer(-1)
|
|
add()
|
|
besselj()
|
|
push(caddr(p1))
|
|
push_integer(-1)
|
|
multiply()
|
|
push(cadr(p1))
|
|
divide()
|
|
push(cadr(p1))
|
|
push(caddr(p1))
|
|
besselj()
|
|
multiply()
|
|
add()
|
|
multiply()
|
|
|
|
dbessely0 = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
push_integer(1)
|
|
besselj()
|
|
multiply()
|
|
push_integer(-1)
|
|
multiply()
|
|
|
|
dbesselyn = ->
|
|
push(cadr(p1))
|
|
push(p2)
|
|
derivative()
|
|
push(cadr(p1))
|
|
push(caddr(p1))
|
|
push_integer(-1)
|
|
add()
|
|
bessely()
|
|
push(caddr(p1))
|
|
push_integer(-1)
|
|
multiply()
|
|
push(cadr(p1))
|
|
divide()
|
|
push(cadr(p1))
|
|
push(caddr(p1))
|
|
bessely()
|
|
multiply()
|
|
add()
|
|
multiply()
|
|
|
|
derivative_of_integral = ->
|
|
push(cadr(p1))
|
|
|
|
|