/
algebra.jl
90 lines (77 loc) · 2.68 KB
/
algebra.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
### Coefficient
## FIXME: Can't specify both. Update: may be possible now
#@mkapprule Coefficient nargs => 2:3 options => Dict(:Method => :SymPy)
@mkapprule Coefficient options => Dict(:Method => :SymPy)
## TODO Merge this with CoefficientSympy
# @doap function Coefficient(args...; kws...)
# meth = get(kws,:Method)
# if meth == :Sympy
@doap function Coefficient(expr, x; kws...)
res = coefficient0(mx,expr,x)
res == :nothing ? mx : res
end
@doap function Coefficient(expr, x, pow; kws...)
pow == 0 && return coefficient_free(mx,expr,x)
res = coefficient0(mx,expr, mxpr(:Power, x,pow))
res == :nothing ? mx : res
end
coefficient0(mx,expr,x::Number) = mx
coefficient0(mx,expr,x) = coefficient(expr,x)
coefficient(expr::TimesT, x) = coefficient_times(expr,[x])
function coefficient(expr::TimesT, x::TimesT)
if isa(x[1],Number)
fac = x[1]
res = coefficient_times(expr,margs(x)[2:end])
res == 0 && return 0
return mmul(res, mpow(fac,-1))
else
coefficient_times(expr,x)
end
end
function coefficient_times(expr::TimesT, coll)
expr == coll && return 1
posns = Symata.oldfindin(expr, coll)
isempty(posns) && return 0
(length(posns) != length(coll)) && return 0
nargs = deleteat!(copy(margs(expr)),posns)
length(nargs) == 1 && return nargs[1]
mxpra(mhead(expr), nargs)
end
coefficient(expr,x) = x == expr ? 1 : 0
coefficient(expr::PlusT,x::PlusT) = x == expr ? 1 : 0
function coefficient(expr::PlusT, x)
nargs = newargs()
for term in expr
res = coefficient(term,x)
if res != 0
push!(nargs,res)
end
end
isempty(nargs) && return 0
MPlusA(nargs)
end
coefficient_free(mx,expr,x::Number) = mx
coefficient_free(mx,expr,x) = coefficient_free1(expr,x)
## Very, very strange bug. The use of macro @extomx sometimes causes segfault during compiling, sometimes not,
## even if all other code does not change.
## Eg.
## 1. Check out a particluar commit and compile and run all tests.
## 2. Edit some files
## 3. Check out same commit. Compiling causes segfault.
## Just adding these comments caused the compliation to succeed.
## Adding the previous line "Just..." now causes compilation to fail
function coefficient_free1(expr,x)
return (freeq(expr,x) && freeq(expr, MPower(x,MBlank()))) ? expr : 0 # this works fine, as well
# return (freeq(expr,x) && freeq(expr, @extomx( $x^_ ))) ? expr : 0 # This is too tempermental
end
function coefficient_free1(expr::PlusT,x)
nargs = newargs()
for term in expr
res = coefficient_free1(term,x)
if res != 0
push!(nargs,res)
end
end
isempty(nargs) && return 0
MPlusA(nargs)
end