@@ -31,28 +31,82 @@ See also `monomial_lt` and `lexlt`.
31
31
"""
32
32
function get_degrees (expr)
33
33
if issym (expr)
34
- ((Symbol (expr),) => 1 ,)
34
+ return ((Symbol (expr),) => 1 ,)
35
35
elseif iscall (expr)
36
- op = operation (expr)
37
- args = sorted_arguments (expr)
38
- if op == (^ ) && args[2 ] isa Number
39
- return map (get_degrees (args[1 ])) do (base, pow)
40
- (base => pow * args[2 ])
41
- end
42
- elseif op == (* )
43
- return mapreduce (get_degrees,
44
- (x,y)-> (x... ,y... ,), args)
45
- elseif op == (+ )
46
- ds = map (get_degrees, args)
47
- _, idx = findmax (x-> sum (last, x, init= 0 ), ds)
48
- return ds[idx]
49
- elseif op == (getindex)
50
- return (Tuple (map (Symbol, args)) => 1 ,)
51
- else
52
- return ((Symbol (" zzzzzzz" , hash (expr)),) => 1 ,)
36
+ # operation-specific degree handling
37
+ return get_degrees (operation (expr), expr)
38
+ else
39
+ return () # skip numbers and unsupported expressions
40
+ end
41
+ end
42
+
43
+ # fallback for unsupported operation
44
+ get_degrees (:: Any , expr) =
45
+ ((Symbol (" zzzzzzz" , hash (expr)),) => 1 ,)
46
+
47
+ _getindex_symbol (arr, i) = Symbol (arr[i])
48
+
49
+ function get_degrees (:: typeof (getindex), expr)
50
+ args = arguments (expr)
51
+ @inbounds return (ntuple (Base. Fix1 (_getindex_symbol, args), length (args)) => 1 ,)
52
+ end
53
+
54
+ function get_degrees (:: typeof (* ), expr)
55
+ args = arguments (expr)
56
+ ds = sizehint! (Vector {Any} (), length (args))
57
+ for arg in args
58
+ degs = get_degrees (arg)
59
+ append! (ds, degs)
60
+ end
61
+ return sort! (ds)
62
+ end
63
+
64
+ function get_degrees (:: typeof (+ ), expr)
65
+ # among the terms find the best in terms of monomial_lt
66
+ sel_degs = ()
67
+ sel_degsum = 0
68
+ for arg in arguments (expr)
69
+ degs = get_degrees (arg)
70
+ degsum = sum (last, degs, init= 0 )
71
+ if (sel_degs == ()) || (degsum > sel_degsum) ||
72
+ (degsum == sel_degsum && lexlt (degs, sel_degs))
73
+ sel_degs, sel_degsum = degs, degsum
74
+ end
75
+ end
76
+ return sel_degs
77
+ end
78
+
79
+ function get_degrees (:: typeof (^ ), expr)
80
+ base_expr, pow_expr = arguments (expr)
81
+ if pow_expr isa Number
82
+ @inbounds degs = map (get_degrees (base_expr)) do (base, pow)
83
+ (base => pow * pow_expr)
84
+ end
85
+ if pow_expr < 0 && length (degs) > 1
86
+ # fix the order after the powers were negated
87
+ isa (degs, AbstractVector) || (degs = collect (degs))
88
+ sort! (degs)
89
+ end
90
+ return degs
91
+ else
92
+ # expression in the power argument is not supported
93
+ return get_degrees (nothing , expr)
94
+ end
95
+ end
96
+
97
+ function get_degrees (:: typeof (/ ), expr)
98
+ nom_expr, denom_expr = arguments (expr)
99
+ if denom_expr isa Number # constant denominator
100
+ return get_degrees (nom_expr)
101
+ elseif nom_expr isa Number # constant nominator
102
+ @inbounds degs = map (get_degrees (denom_expr)) do (base, pow)
103
+ (base => - pow)
53
104
end
105
+ isa (degs, AbstractVector) || (degs = collect (degs))
106
+ return sort! (degs)
54
107
else
55
- return ()
108
+ # TODO expressions in both nom and denom are not yet supported
109
+ return get_degrees (nothing , expr)
56
110
end
57
111
end
58
112
0 commit comments