mathai 0.7.8__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mathai/expand.py +2 -20
- mathai/fraction.py +82 -98
- mathai/integrate.py +10 -4
- mathai/linear.py +12 -21
- mathai/logic.py +5 -8
- mathai/matrix.py +12 -52
- mathai/ode.py +164 -104
- mathai/parser.py +2 -8
- mathai/pde.py +5 -10
- mathai/simplify.py +26 -175
- mathai/structure.py +3 -3
- mathai/tool.py +19 -28
- mathai/trig.py +44 -33
- mathai/univariate_inequality.py +1 -2
- {mathai-0.7.8.dist-info → mathai-0.8.0.dist-info}/METADATA +1 -1
- mathai-0.8.0.dist-info/RECORD +28 -0
- mathai/console.py +0 -84
- mathai/parsetab.py +0 -61
- mathai-0.7.8.dist-info/RECORD +0 -30
- {mathai-0.7.8.dist-info → mathai-0.8.0.dist-info}/WHEEL +0 -0
- {mathai-0.7.8.dist-info → mathai-0.8.0.dist-info}/top_level.txt +0 -0
mathai/simplify.py
CHANGED
|
@@ -15,9 +15,9 @@ def convert_to_basic(node):
|
|
|
15
15
|
return node
|
|
16
16
|
|
|
17
17
|
def clear_div(eq, denom):
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
lst = factor_generation(eq)
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
if tree_form("d_0") in lst:
|
|
22
22
|
return tree_form("d_0"), True
|
|
23
23
|
|
|
@@ -32,16 +32,16 @@ def clear_div(eq, denom):
|
|
|
32
32
|
eq2 = []
|
|
33
33
|
eq3 = []
|
|
34
34
|
for item in lst:
|
|
35
|
-
if frac(item) is not None
|
|
35
|
+
if frac(item) is not None:
|
|
36
36
|
eq2.append(item)
|
|
37
37
|
else:
|
|
38
38
|
eq3.append(item)
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
if eq3 == []:
|
|
41
41
|
return product(eq2), True
|
|
42
42
|
return product(eq3), sign
|
|
43
43
|
lst4 = []
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
for item in lst:
|
|
46
46
|
if item.name == "f_pow":
|
|
47
47
|
tmp = frac(item.children[1])
|
|
@@ -49,73 +49,18 @@ def clear_div(eq, denom):
|
|
|
49
49
|
lst4.append(item)
|
|
50
50
|
else:
|
|
51
51
|
lst4.append(item)
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
lst2 = []
|
|
54
54
|
for item in lst4:
|
|
55
|
-
if frac(item) is None
|
|
55
|
+
if frac(item) is None:
|
|
56
56
|
lst2.append(item)
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
if lst2 == []:
|
|
59
59
|
return product(lst4), sign
|
|
60
60
|
return product(lst2), sign
|
|
61
|
-
'''
|
|
62
|
-
def multiply_node(eq):
|
|
63
|
-
if not eq.name.startswith("f_"):
|
|
64
|
-
return eq
|
|
65
|
-
if eq.name == "f_mul":
|
|
66
|
-
con = 1
|
|
67
|
-
eq2 = TreeNode("f_mul", [])
|
|
68
|
-
for i in range(len(eq.children)-1,-1,-1):
|
|
69
|
-
if frac(eq.children[i]) is not None:
|
|
70
|
-
con = con * frac(eq.children[i])
|
|
71
|
-
else:
|
|
72
|
-
eq2.children.append(eq.children[i])
|
|
73
|
-
if con == 0:
|
|
74
|
-
return tree_form("d_0")
|
|
75
|
-
eq2.name = eq.name
|
|
76
|
-
eq = eq2
|
|
77
61
|
|
|
78
|
-
lst = {}
|
|
79
|
-
for child in eq.children:
|
|
80
|
-
power = tree_form("d_1")
|
|
81
|
-
con2 = ""
|
|
82
|
-
if child.name == "f_pow":
|
|
83
|
-
con2 = child.children[0]
|
|
84
|
-
power = child.children[1]
|
|
85
|
-
else:
|
|
86
|
-
con2 = child
|
|
87
|
-
if con2 in lst.keys():
|
|
88
|
-
lst[con2] = lst[con2] + power
|
|
89
|
-
else:
|
|
90
|
-
lst[con2] = power
|
|
91
|
-
eq3 = TreeNode("f_mul", [])
|
|
92
|
-
|
|
93
|
-
for kv in lst.keys():
|
|
94
|
-
tmp3 = lst[kv]
|
|
95
|
-
if tmp3 == tree_form("d_1"):
|
|
96
|
-
eq3.children.append(kv)
|
|
97
|
-
elif tmp3 == tree_form("d_0"):
|
|
98
|
-
continue
|
|
99
|
-
else:
|
|
100
|
-
eq3.children.append(kv ** tmp3)
|
|
101
|
-
|
|
102
|
-
tmp3 = frac_to_tree(con)
|
|
103
|
-
if tmp3 != tree_form("d_1"):
|
|
104
|
-
eq3.children.append(tmp3)
|
|
105
|
-
eq = eq3
|
|
106
|
-
eq4 = TreeNode(eq.name, [])
|
|
107
|
-
if eq.children == []:
|
|
108
|
-
return tree_form("d_1")
|
|
109
|
-
if len(eq.children) == 1:
|
|
110
|
-
eq4 = eq.children[0]
|
|
111
|
-
eq = eq4
|
|
112
|
-
return TreeNode(eq.name, [multiply_node(child) for child in eq.children])
|
|
113
|
-
'''
|
|
114
62
|
def multiply_node(equation):
|
|
115
|
-
|
|
116
|
-
Iterative version of multiply_node without using TreeNode as dict key.
|
|
117
|
-
"""
|
|
118
|
-
# Stack: (node, child_index, partially_processed_children)
|
|
63
|
+
|
|
119
64
|
if equation is None:
|
|
120
65
|
return None
|
|
121
66
|
stack = [(equation, 0, [])]
|
|
@@ -123,13 +68,11 @@ def multiply_node(equation):
|
|
|
123
68
|
while stack:
|
|
124
69
|
node, child_index, processed_children = stack.pop()
|
|
125
70
|
|
|
126
|
-
# If all children processed
|
|
127
71
|
if child_index >= len(node.children):
|
|
128
72
|
node.children = processed_children
|
|
129
73
|
|
|
130
|
-
# Only process multiplication nodes
|
|
131
74
|
if node.name == "f_mul":
|
|
132
|
-
|
|
75
|
+
|
|
133
76
|
con = 1
|
|
134
77
|
new_children = []
|
|
135
78
|
for child in reversed(node.children):
|
|
@@ -141,7 +84,7 @@ def multiply_node(equation):
|
|
|
141
84
|
|
|
142
85
|
if con == 0:
|
|
143
86
|
node = tree_form("d_0")
|
|
144
|
-
|
|
87
|
+
|
|
145
88
|
if stack:
|
|
146
89
|
parent, idx, parent_children = stack.pop()
|
|
147
90
|
parent_children.append(node)
|
|
@@ -152,8 +95,6 @@ def multiply_node(equation):
|
|
|
152
95
|
|
|
153
96
|
node.children = new_children
|
|
154
97
|
|
|
155
|
-
# Step 2: combine powers of same base iteratively
|
|
156
|
-
# Instead of using dict, we collect (base, exponent) in a list
|
|
157
98
|
base_powers = []
|
|
158
99
|
for child in node.children:
|
|
159
100
|
if child.name == "f_pow":
|
|
@@ -162,17 +103,15 @@ def multiply_node(equation):
|
|
|
162
103
|
base = child
|
|
163
104
|
power = tree_form("d_1")
|
|
164
105
|
|
|
165
|
-
# Look for existing base in base_powers (by structural equality)
|
|
166
106
|
found = False
|
|
167
107
|
for i, (b, p) in enumerate(base_powers):
|
|
168
|
-
if b == base:
|
|
108
|
+
if b == base:
|
|
169
109
|
base_powers[i] = (b, p + power)
|
|
170
110
|
found = True
|
|
171
111
|
break
|
|
172
112
|
if not found:
|
|
173
113
|
base_powers.append((base, power))
|
|
174
114
|
|
|
175
|
-
# Step 3: rebuild multiplication node
|
|
176
115
|
new_mul = TreeNode("f_mul", [])
|
|
177
116
|
for base, power in base_powers:
|
|
178
117
|
if power == tree_form("d_1"):
|
|
@@ -182,12 +121,10 @@ def multiply_node(equation):
|
|
|
182
121
|
else:
|
|
183
122
|
new_mul.children.append(TreeNode("f_pow", [base, power]))
|
|
184
123
|
|
|
185
|
-
# Step 4: add numeric constant
|
|
186
124
|
con_tree = frac_to_tree(con)
|
|
187
125
|
if con_tree != tree_form("d_1"):
|
|
188
126
|
new_mul.children.append(con_tree)
|
|
189
127
|
|
|
190
|
-
# Step 5: simplify trivial cases
|
|
191
128
|
if not new_mul.children:
|
|
192
129
|
node = tree_form("d_1")
|
|
193
130
|
elif len(new_mul.children) == 1:
|
|
@@ -195,100 +132,22 @@ def multiply_node(equation):
|
|
|
195
132
|
else:
|
|
196
133
|
node = new_mul
|
|
197
134
|
|
|
198
|
-
# Return node to parent
|
|
199
135
|
if stack:
|
|
200
136
|
parent, idx, parent_children = stack.pop()
|
|
201
137
|
parent_children.append(node)
|
|
202
138
|
stack.append((parent, idx + 1, parent_children))
|
|
203
139
|
else:
|
|
204
|
-
return node
|
|
140
|
+
return node
|
|
205
141
|
|
|
206
142
|
else:
|
|
207
|
-
|
|
143
|
+
|
|
208
144
|
stack.append((node, child_index, processed_children))
|
|
209
|
-
|
|
145
|
+
|
|
210
146
|
child = node.children[child_index]
|
|
211
147
|
stack.append((child, 0, []))
|
|
212
|
-
'''
|
|
213
|
-
def addition_node(eq):
|
|
214
|
-
if not eq.name.startswith("f_"):
|
|
215
|
-
return eq
|
|
216
|
-
if eq.name == "f_add":
|
|
217
|
-
con = 0
|
|
218
|
-
eq2 = TreeNode("f_add", [])
|
|
219
|
-
for i in range(len(eq.children)-1,-1,-1):
|
|
220
|
-
n = frac(eq.children[i])
|
|
221
|
-
if n is not None:
|
|
222
|
-
con = con + n
|
|
223
|
-
else:
|
|
224
|
-
eq2.children.append(eq.children[i])
|
|
225
|
-
eq2.name = eq.name
|
|
226
|
-
eq = eq2
|
|
227
148
|
|
|
228
|
-
lst = {}
|
|
229
|
-
for child in eq.children:
|
|
230
|
-
power = TreeNode("f_mul", [])
|
|
231
|
-
con2 = None
|
|
232
|
-
con3 = TreeNode("f_mul", [])
|
|
233
|
-
power2 = None
|
|
234
|
-
|
|
235
|
-
if child.name == "f_mul":
|
|
236
|
-
for i in range(len(child.children)):
|
|
237
|
-
if "v_" not in str_form(child.children[i]):
|
|
238
|
-
if child.children[i] != tree_form("d_0"):
|
|
239
|
-
power.children.append(child.children[i])
|
|
240
|
-
else:
|
|
241
|
-
if child.children[i] != tree_form("d_1"):
|
|
242
|
-
con3.children.append(child.children[i])
|
|
243
|
-
if len(con3.children) == 0:
|
|
244
|
-
con2 = tree_form("d_1")
|
|
245
|
-
elif len(con3.children) == 1:
|
|
246
|
-
con2 = con3.children[0]
|
|
247
|
-
else:
|
|
248
|
-
con2 = con3
|
|
249
|
-
else:
|
|
250
|
-
con2 = child
|
|
251
|
-
|
|
252
|
-
if power.children == []:
|
|
253
|
-
power2 = tree_form("d_1")
|
|
254
|
-
elif len(power.children) == 1:
|
|
255
|
-
power2 = power.children[0]
|
|
256
|
-
else:
|
|
257
|
-
power2 = power
|
|
258
|
-
|
|
259
|
-
if con2 in lst.keys():
|
|
260
|
-
lst[con2] = lst[con2] + power2
|
|
261
|
-
else:
|
|
262
|
-
lst[con2] = power2
|
|
263
|
-
eq3 = TreeNode("f_add", [])
|
|
264
|
-
|
|
265
|
-
for kv in lst.keys():
|
|
266
|
-
tmp3 = lst[kv]
|
|
267
|
-
if tmp3 == tree_form("d_1"):
|
|
268
|
-
eq3.children.append(kv)
|
|
269
|
-
elif tmp3 == tree_form("d_0"):
|
|
270
|
-
continue
|
|
271
|
-
else:
|
|
272
|
-
eq3.children.append(kv * tmp3)
|
|
273
|
-
|
|
274
|
-
eq = eq3
|
|
275
|
-
eq4 = None
|
|
276
|
-
tmp3 = frac_to_tree(con)
|
|
277
|
-
if tmp3 != tree_form("d_0"):
|
|
278
|
-
eq.children.append(tmp3)
|
|
279
|
-
if eq.children == []:
|
|
280
|
-
return tree_form("d_0")
|
|
281
|
-
if len(eq.children) == 1:
|
|
282
|
-
eq4 = eq.children[0]
|
|
283
|
-
eq = eq4
|
|
284
|
-
return TreeNode(eq.name, [addition_node(child) for child in eq.children])
|
|
285
|
-
'''
|
|
286
149
|
def addition_node(equation):
|
|
287
|
-
|
|
288
|
-
Iterative version of addition_node.
|
|
289
|
-
Combines constants and like terms in addition nodes.
|
|
290
|
-
"""
|
|
291
|
-
# Stack: (node, child_index, partially_processed_children)
|
|
150
|
+
|
|
292
151
|
if equation is None:
|
|
293
152
|
return None
|
|
294
153
|
stack = [(equation, 0, [])]
|
|
@@ -296,13 +155,11 @@ def addition_node(equation):
|
|
|
296
155
|
while stack:
|
|
297
156
|
node, child_index, processed_children = stack.pop()
|
|
298
157
|
|
|
299
|
-
# If all children are processed
|
|
300
158
|
if child_index >= len(node.children):
|
|
301
159
|
node.children = processed_children
|
|
302
160
|
|
|
303
|
-
# Only process addition nodes
|
|
304
161
|
if node.name == "f_add":
|
|
305
|
-
|
|
162
|
+
|
|
306
163
|
con = 0
|
|
307
164
|
new_children = []
|
|
308
165
|
for child in reversed(node.children):
|
|
@@ -314,11 +171,9 @@ def addition_node(equation):
|
|
|
314
171
|
|
|
315
172
|
node.children = new_children
|
|
316
173
|
|
|
317
|
-
# Step 2: combine like terms iteratively
|
|
318
|
-
# We store (base, power) pairs in a list (avoid dict/hash)
|
|
319
174
|
base_terms = []
|
|
320
175
|
for child in node.children:
|
|
321
|
-
|
|
176
|
+
|
|
322
177
|
power_node = TreeNode("f_mul", [])
|
|
323
178
|
base_node = None
|
|
324
179
|
mul_node = TreeNode("f_mul", [])
|
|
@@ -326,10 +181,10 @@ def addition_node(equation):
|
|
|
326
181
|
|
|
327
182
|
if child.name == "f_mul":
|
|
328
183
|
for c in child.children:
|
|
329
|
-
if frac(c) is not None:
|
|
184
|
+
if frac(c) is not None:
|
|
330
185
|
if c != tree_form("d_0"):
|
|
331
186
|
power_node.children.append(c)
|
|
332
|
-
else:
|
|
187
|
+
else:
|
|
333
188
|
if c != tree_form("d_1"):
|
|
334
189
|
mul_node.children.append(c)
|
|
335
190
|
if len(mul_node.children) == 0:
|
|
@@ -348,7 +203,6 @@ def addition_node(equation):
|
|
|
348
203
|
else:
|
|
349
204
|
multiplier_node = power_node
|
|
350
205
|
|
|
351
|
-
# Combine like terms structurally
|
|
352
206
|
found = False
|
|
353
207
|
for i, (b, m) in enumerate(base_terms):
|
|
354
208
|
if b == base_node:
|
|
@@ -358,7 +212,6 @@ def addition_node(equation):
|
|
|
358
212
|
if not found:
|
|
359
213
|
base_terms.append((base_node, multiplier_node))
|
|
360
214
|
|
|
361
|
-
# Step 3: rebuild addition node
|
|
362
215
|
new_add = TreeNode("f_add", [])
|
|
363
216
|
for base, multiplier in base_terms:
|
|
364
217
|
if multiplier == tree_form("d_1"):
|
|
@@ -368,12 +221,10 @@ def addition_node(equation):
|
|
|
368
221
|
else:
|
|
369
222
|
new_add.children.append(base * multiplier)
|
|
370
223
|
|
|
371
|
-
# Step 4: add numeric constant
|
|
372
224
|
con_tree = frac_to_tree(con)
|
|
373
225
|
if con_tree != tree_form("d_0"):
|
|
374
226
|
new_add.children.append(con_tree)
|
|
375
227
|
|
|
376
|
-
# Step 5: simplify trivial cases
|
|
377
228
|
if not new_add.children:
|
|
378
229
|
node = tree_form("d_0")
|
|
379
230
|
elif len(new_add.children) == 1:
|
|
@@ -381,19 +232,18 @@ def addition_node(equation):
|
|
|
381
232
|
else:
|
|
382
233
|
node = new_add
|
|
383
234
|
|
|
384
|
-
# Return node to parent
|
|
385
235
|
if stack:
|
|
386
236
|
parent, idx, parent_children = stack.pop()
|
|
387
237
|
parent_children.append(node)
|
|
388
238
|
stack.append((parent, idx + 1, parent_children))
|
|
389
239
|
else:
|
|
390
|
-
|
|
240
|
+
|
|
391
241
|
return node
|
|
392
242
|
|
|
393
243
|
else:
|
|
394
|
-
|
|
244
|
+
|
|
395
245
|
stack.append((node, child_index, processed_children))
|
|
396
|
-
|
|
246
|
+
|
|
397
247
|
child = node.children[child_index]
|
|
398
248
|
stack.append((child, 0, []))
|
|
399
249
|
|
|
@@ -422,7 +272,7 @@ def other_node(eq):
|
|
|
422
272
|
if eq.children[0].name == "f_abs" and eq.children[1].name.startswith("d_")\
|
|
423
273
|
and int(eq.children[1].name[2:]) % 2 == 0:
|
|
424
274
|
return eq.children[0].children[0] ** eq.children[1]
|
|
425
|
-
|
|
275
|
+
|
|
426
276
|
if eq.children[0].name == "f_mul":
|
|
427
277
|
n = frac(eq.children[1])
|
|
428
278
|
if n is not None and n < 0 and n.numerator % 2 == 1 and n.denominator == 1:
|
|
@@ -517,7 +367,7 @@ def simplify(eq, basic=True):
|
|
|
517
367
|
tmp2 = simplify(eq.children[0] - eq.children[1])
|
|
518
368
|
tmp, denom = clear_div(tmp2, denom)
|
|
519
369
|
tmp = simplify(tmp)
|
|
520
|
-
|
|
370
|
+
|
|
521
371
|
value2 = eq.name[2:]
|
|
522
372
|
if denom is False:
|
|
523
373
|
value2 = {"ge":"le", "le":"ge", "gt":"lt", "lt":"gt", "eq":"eq"}[value2]
|
|
@@ -529,3 +379,4 @@ def simplify(eq, basic=True):
|
|
|
529
379
|
eq = convert_to_basic(eq)
|
|
530
380
|
eq = solve3(eq)
|
|
531
381
|
return eq
|
|
382
|
+
|
mathai/structure.py
CHANGED
|
@@ -2,7 +2,7 @@ import itertools
|
|
|
2
2
|
from .simplify import simplify
|
|
3
3
|
from .base import *
|
|
4
4
|
|
|
5
|
-
def structure(equation, formula, formula_out=None, only_const=False):
|
|
5
|
+
def structure(equation, formula, formula_out=None, only_const=False, wrt=None):
|
|
6
6
|
varlist = {}
|
|
7
7
|
def helper(equation, formula):
|
|
8
8
|
nonlocal varlist
|
|
@@ -60,7 +60,7 @@ def structure(equation, formula, formula_out=None, only_const=False):
|
|
|
60
60
|
for item in lst(formula):
|
|
61
61
|
varlist = {}
|
|
62
62
|
if helper(equation, item):
|
|
63
|
-
if only_const and any(
|
|
63
|
+
if only_const and any(contain(varlist[key], tree_form(wrt)) for key in varlist.keys()):
|
|
64
64
|
continue
|
|
65
65
|
if formula_out is None:
|
|
66
66
|
return varlist
|
|
@@ -90,7 +90,7 @@ def transform_formula(equation, wrt, formula_list, var, expr):
|
|
|
90
90
|
if var != "":
|
|
91
91
|
p = True
|
|
92
92
|
try:
|
|
93
|
-
out = structure(equation.copy_tree(), copy.deepcopy(item[0]), copy.deepcopy(item[1]), p)
|
|
93
|
+
out = structure(equation.copy_tree(), copy.deepcopy(item[0]), copy.deepcopy(item[1]), p, wrt)
|
|
94
94
|
if out is not None:
|
|
95
95
|
out = simplify(out)
|
|
96
96
|
|
mathai/tool.py
CHANGED
|
@@ -8,68 +8,58 @@ def poly_div(dividend_coeffs, divisor_coeffs):
|
|
|
8
8
|
"""
|
|
9
9
|
Perform polynomial division using coefficients with symbolic simplification.
|
|
10
10
|
"""
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
dividend = [item.copy_tree() for item in dividend_coeffs]
|
|
13
13
|
divisor = [item.copy_tree() for item in divisor_coeffs]
|
|
14
|
-
|
|
15
|
-
# Remove leading zeros
|
|
14
|
+
|
|
16
15
|
while len(dividend) > 1 and simplify(dividend[0]) == 0:
|
|
17
16
|
dividend.pop(0)
|
|
18
17
|
while len(divisor) > 1 and simplify(divisor[0]) == 0:
|
|
19
18
|
divisor.pop(0)
|
|
20
|
-
|
|
21
|
-
# Validate divisor
|
|
19
|
+
|
|
22
20
|
if len(divisor) == 0 or simplify(divisor[0]) == 0:
|
|
23
21
|
raise ValueError("Invalid divisor")
|
|
24
|
-
|
|
22
|
+
|
|
25
23
|
if len(dividend) < len(divisor):
|
|
26
24
|
return [tree_form("d_0")], [item.copy_tree() for item in dividend]
|
|
27
|
-
|
|
28
|
-
# Calculate degrees
|
|
25
|
+
|
|
29
26
|
deg_p = len(dividend) - 1
|
|
30
27
|
deg_q = len(divisor) - 1
|
|
31
28
|
deg_quot = deg_p - deg_q
|
|
32
|
-
|
|
33
|
-
# Initialize quotient (highest degree first)
|
|
29
|
+
|
|
34
30
|
quotient = [tree_form("d_0")] * (deg_quot + 1)
|
|
35
|
-
|
|
36
|
-
# Working dividend - keep original structure
|
|
31
|
+
|
|
37
32
|
working_dividend = [item.copy_tree() for item in dividend]
|
|
38
|
-
|
|
39
|
-
# Long division - align by current leading terms
|
|
33
|
+
|
|
40
34
|
for k in range(deg_quot, -1, -1):
|
|
41
|
-
|
|
35
|
+
|
|
42
36
|
while len(working_dividend) > 1 and simplify(working_dividend[0]) == 0:
|
|
43
37
|
working_dividend.pop(0)
|
|
44
|
-
|
|
38
|
+
|
|
45
39
|
if len(working_dividend) == 0 or simplify(working_dividend[0]) == 0:
|
|
46
40
|
continue
|
|
47
|
-
|
|
48
|
-
# Calculate quotient term for degree k
|
|
41
|
+
|
|
49
42
|
leading_ratio = simplify(working_dividend[0] / divisor[0])
|
|
50
43
|
quotient[k] = leading_ratio
|
|
51
|
-
|
|
52
|
-
# Subtract leading_ratio * divisor (aligned at leading terms)
|
|
44
|
+
|
|
53
45
|
new_dividend = []
|
|
54
46
|
for i in range(max(len(working_dividend), len(divisor))):
|
|
55
47
|
dividend_term = working_dividend[i] if i < len(working_dividend) else tree_form("d_0")
|
|
56
48
|
divisor_term = simplify(leading_ratio * divisor[i]) if i < len(divisor) else tree_form("d_0")
|
|
57
49
|
result = simplify(dividend_term - divisor_term)
|
|
58
50
|
new_dividend.append(result)
|
|
59
|
-
|
|
51
|
+
|
|
60
52
|
working_dividend = new_dividend
|
|
61
|
-
|
|
62
|
-
# Remainder is terms with degree < deg_q (last deg_q terms of final dividend)
|
|
53
|
+
|
|
63
54
|
remainder = working_dividend[-(deg_q):] if len(working_dividend) > deg_q else working_dividend
|
|
64
55
|
while len(remainder) > 1 and simplify(remainder[0]) == 0:
|
|
65
56
|
remainder.pop(0)
|
|
66
57
|
if not remainder:
|
|
67
58
|
remainder = [tree_form("d_0")]
|
|
68
|
-
|
|
69
|
-
# Clean quotient trailing zeros
|
|
59
|
+
|
|
70
60
|
while len(quotient) > 1 and simplify(quotient[-1]) == 0:
|
|
71
61
|
quotient.pop()
|
|
72
|
-
|
|
62
|
+
|
|
73
63
|
return quotient, remainder
|
|
74
64
|
|
|
75
65
|
def unpoly(eq, var):
|
|
@@ -80,7 +70,7 @@ def unpoly(eq, var):
|
|
|
80
70
|
|
|
81
71
|
def longdiv(p, q, p_min=0, q_min=0):
|
|
82
72
|
p, q = simplify(p), simplify(q)
|
|
83
|
-
|
|
73
|
+
|
|
84
74
|
var = set(vlist(p)) & set(vlist(q))
|
|
85
75
|
if len(var) > 0:
|
|
86
76
|
var = list(var)[0]
|
|
@@ -114,7 +104,7 @@ def enclose_const(eq):
|
|
|
114
104
|
nonlocal alloclst, dic
|
|
115
105
|
if frac(eq) is not None:
|
|
116
106
|
return eq
|
|
117
|
-
|
|
107
|
+
|
|
118
108
|
if "v_" not in str_form(eq):
|
|
119
109
|
if eq not in dic.keys():
|
|
120
110
|
n = alloclst.pop(0)
|
|
@@ -161,3 +151,4 @@ def poly(eq, to_compute, m=10):
|
|
|
161
151
|
final.append(substitute_val(item, 0, to_compute)/tree_form("d_"+str(math.factorial(index))))
|
|
162
152
|
|
|
163
153
|
return [expand(simplify(item)) for item in final][::-1]
|
|
154
|
+
|