pimath 0.2.14 → 0.2.15
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.
- package/dist/pimath.js +850 -1879
- package/dist/pimath.js.map +1 -1
- package/package.json +1 -1
- package/src/algebra/equation.ts +562 -558
- package/src/algebra/equationSolver.ts +489 -489
- package/src/algebra/factor.ts +396 -392
- package/src/algebra/linearSystem.ts +446 -442
- package/src/algebra/matrix.ts +515 -511
- package/src/algebra/monom.ts +932 -928
- package/src/algebra/polyFactor.ts +724 -720
- package/src/algebra/polynom.ts +1233 -1229
- package/src/coefficients/fraction.ts +907 -748
- package/src/coefficients/root.ts +500 -359
- package/src/geometry/TupleN.ts +129 -129
- package/src/geometry/circle.ts +455 -455
- package/src/geometry/line.ts +658 -654
- package/src/geometry/point.ts +105 -105
- package/src/geometry/sphere3.ts +2 -2
- package/src/geometry/triangle.ts +488 -488
- package/src/geometry/vector.ts +230 -226
- package/src/numeric.ts +136 -51
- package/src/pimath.interface.ts +2 -0
- package/types/algebra/equation.d.ts +1 -0
- package/types/algebra/equation.d.ts.map +1 -1
- package/types/algebra/equationSolver.d.ts.map +1 -1
- package/types/algebra/factor.d.ts +1 -0
- package/types/algebra/factor.d.ts.map +1 -1
- package/types/algebra/linearSystem.d.ts +1 -0
- package/types/algebra/linearSystem.d.ts.map +1 -1
- package/types/algebra/matrix.d.ts +6 -5
- package/types/algebra/matrix.d.ts.map +1 -1
- package/types/algebra/monom.d.ts +1 -0
- package/types/algebra/monom.d.ts.map +1 -1
- package/types/algebra/polyFactor.d.ts +1 -0
- package/types/algebra/polyFactor.d.ts.map +1 -1
- package/types/algebra/polynom.d.ts +1 -0
- package/types/algebra/polynom.d.ts.map +1 -1
- package/types/coefficients/fraction.d.ts +62 -53
- package/types/coefficients/fraction.d.ts.map +1 -1
- package/types/coefficients/root.d.ts +3 -0
- package/types/coefficients/root.d.ts.map +1 -1
- package/types/geometry/TupleN.d.ts +1 -1
- package/types/geometry/TupleN.d.ts.map +1 -1
- package/types/geometry/circle.d.ts.map +1 -1
- package/types/geometry/line.d.ts +1 -0
- package/types/geometry/line.d.ts.map +1 -1
- package/types/geometry/point.d.ts.map +1 -1
- package/types/geometry/sphere3.d.ts +2 -2
- package/types/geometry/sphere3.d.ts.map +1 -1
- package/types/geometry/triangle.d.ts.map +1 -1
- package/types/geometry/vector.d.ts +1 -0
- package/types/geometry/vector.d.ts.map +1 -1
- package/types/index.d.ts +3 -3
- package/types/numeric.d.ts +4 -4
- package/types/numeric.d.ts.map +1 -1
- package/types/pimath.interface.d.ts +1 -0
- package/types/pimath.interface.d.ts.map +1 -1
- package/types/primes.data.d.ts +2 -0
- package/types/primes.data.d.ts.map +1 -0
|
@@ -1,720 +1,724 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
FACTOR_TABLE_OF_SIGNS,
|
|
3
|
-
IAlgebra,
|
|
4
|
-
IExpression,
|
|
5
|
-
InputAlgebra,
|
|
6
|
-
InputValue,
|
|
7
|
-
IPiMathObject,
|
|
8
|
-
literalType,
|
|
9
|
-
POLYFACTOR_TABLE_OF_SIGNS,
|
|
10
|
-
TABLE_OF_SIGNS_VALUES
|
|
11
|
-
} from "../pimath.interface"
|
|
12
|
-
import {Fraction} from "../coefficients"
|
|
13
|
-
import {MathError, NotImplementedError, ParseError} from "../errors"
|
|
14
|
-
import {Factor, FACTOR_DISPLAY} from "./factor"
|
|
15
|
-
import {Polynom} from "./polynom"
|
|
16
|
-
import type {Solution} from "../analyze"
|
|
17
|
-
import {splitIfOutsideParentheses, stripParenthesis} from "../helpers"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// PolyFactor is a class that represents a polynomial in factored form.
|
|
21
|
-
export class PolyFactor implements IPiMathObject<PolyFactor>,
|
|
22
|
-
IExpression<PolyFactor>,
|
|
23
|
-
IAlgebra<PolyFactor> {
|
|
24
|
-
|
|
25
|
-
#displayMode: FACTOR_DISPLAY = FACTOR_DISPLAY.POWER
|
|
26
|
-
#factors: Factor[] = []
|
|
27
|
-
|
|
28
|
-
constructor(...values: (InputAlgebra<Polynom> | Factor | PolyFactor)[]) {
|
|
29
|
-
this.parse(...values)
|
|
30
|
-
return this
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// Init the factors list
|
|
35
|
-
this.#factors = []
|
|
36
|
-
|
|
37
|
-
// Nothing to create
|
|
38
|
-
if (values.length === 0) {
|
|
39
|
-
return this
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
values.forEach(value => {
|
|
43
|
-
if(typeof value==="string"){
|
|
44
|
-
return this.fromString(value)
|
|
45
|
-
}else if (value instanceof PolyFactor) {
|
|
46
|
-
this.#factors.push(...value.factors.map(f => f.clone()))
|
|
47
|
-
} else {
|
|
48
|
-
this.#factors.push(new Factor(value))
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
return this
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
this
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
return this
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return new
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
this.#factors
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
this
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
//
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
)
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
return
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
return this.#factors.every(f => f.
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
return
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
this.#factors
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
return this
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
//
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
return
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
1
|
+
import type {
|
|
2
|
+
FACTOR_TABLE_OF_SIGNS,
|
|
3
|
+
IAlgebra,
|
|
4
|
+
IExpression,
|
|
5
|
+
InputAlgebra,
|
|
6
|
+
InputValue,
|
|
7
|
+
IPiMathObject,
|
|
8
|
+
literalType,
|
|
9
|
+
POLYFACTOR_TABLE_OF_SIGNS,
|
|
10
|
+
TABLE_OF_SIGNS_VALUES
|
|
11
|
+
} from "../pimath.interface"
|
|
12
|
+
import {Fraction} from "../coefficients"
|
|
13
|
+
import {MathError, NotImplementedError, ParseError} from "../errors"
|
|
14
|
+
import {Factor, FACTOR_DISPLAY} from "./factor"
|
|
15
|
+
import {Polynom} from "./polynom"
|
|
16
|
+
import type {Solution} from "../analyze"
|
|
17
|
+
import {splitIfOutsideParentheses, stripParenthesis} from "../helpers"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// PolyFactor is a class that represents a polynomial in factored form.
|
|
21
|
+
export class PolyFactor implements IPiMathObject<PolyFactor>,
|
|
22
|
+
IExpression<PolyFactor>,
|
|
23
|
+
IAlgebra<PolyFactor> {
|
|
24
|
+
|
|
25
|
+
#displayMode: FACTOR_DISPLAY = FACTOR_DISPLAY.POWER
|
|
26
|
+
#factors: Factor[] = []
|
|
27
|
+
|
|
28
|
+
constructor(...values: (InputAlgebra<Polynom> | Factor | PolyFactor)[]) {
|
|
29
|
+
this.parse(...values)
|
|
30
|
+
return this
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
parse(...values: (InputAlgebra<Polynom> | Factor | PolyFactor)[]): this {
|
|
34
|
+
// Init the factors list
|
|
35
|
+
this.#factors = []
|
|
36
|
+
|
|
37
|
+
// Nothing to create
|
|
38
|
+
if (values.length === 0) {
|
|
39
|
+
return this
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
values.forEach(value => {
|
|
43
|
+
if(typeof value==="string"){
|
|
44
|
+
return this.fromString(value)
|
|
45
|
+
}else if (value instanceof PolyFactor) {
|
|
46
|
+
this.#factors.push(...value.factors.map(f => f.clone()))
|
|
47
|
+
} else {
|
|
48
|
+
this.#factors.push(new Factor(value))
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return this
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
copy(): this {
|
|
56
|
+
throw new NotImplementedError("copy() is not yet implemented for PolyFactor")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
clone(): PolyFactor {
|
|
60
|
+
return new PolyFactor(...this.#factors.map(f => f.clone()))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
get tex(): string {
|
|
64
|
+
const {num, den} = this.#extractNumeratorAndDenominator()
|
|
65
|
+
|
|
66
|
+
if (den.length === 0) {
|
|
67
|
+
if (num.length === 1) {
|
|
68
|
+
return num[0].asSingle.tex
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return num.map(f => f.tex).join("")
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// There is a numerator and a denominator
|
|
75
|
+
const numTeX = num.length === 1 ? num[0].asSingle.tex : num.map(f => f.tex).join("")
|
|
76
|
+
const denTeX = den.length === 1 ? den[0].asSingle.tex : den.map(f => f.tex).join("")
|
|
77
|
+
|
|
78
|
+
return `\\frac{ ${numTeX} }{ ${denTeX} }`
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get display(): string {
|
|
83
|
+
const {num, den} = this.#extractNumeratorAndDenominator()
|
|
84
|
+
|
|
85
|
+
if (den.length === 0) {
|
|
86
|
+
if (num.length === 1) {
|
|
87
|
+
return num[0].asSingle.display
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return num.map((f, index) =>
|
|
91
|
+
index === 0 && f.polynom.monoms.length === 1 ? f.asSingle.display : f.display
|
|
92
|
+
).join("")
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// There is a numerator and a denominator
|
|
96
|
+
const numTeX = num.length === 1 ? num[0].asSingle.display : num.map(f => f.display).join("")
|
|
97
|
+
const denTeX = den.length === 1 ? den[0].asSingle.display : den.map(f => f.display).join("")
|
|
98
|
+
|
|
99
|
+
return `(${numTeX})/(${denTeX})`
|
|
100
|
+
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
static #gcdWith(PF1: PolyFactor, PF2: PolyFactor): PolyFactor {
|
|
107
|
+
// Get all factors of the two polynomials
|
|
108
|
+
// Find the common factors
|
|
109
|
+
const factors1 = keyFactors(PF1)
|
|
110
|
+
|
|
111
|
+
const factors2 = keyFactors(PF2)
|
|
112
|
+
|
|
113
|
+
const common = Object.keys(factors1).filter(k => Object.hasOwn(factors2, k))
|
|
114
|
+
|
|
115
|
+
// Find the minimum power of the common factors
|
|
116
|
+
const factors = common.map(k => {
|
|
117
|
+
const power = factors1[k].reduce((acc, f) => acc.add(f.power), new Fraction('0'))
|
|
118
|
+
const power2 = factors2[k].reduce((acc, f) => acc.add(f.power), new Fraction('0'))
|
|
119
|
+
return new Factor(k, Fraction.min(power, power2))
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
return new PolyFactor(...factors)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static #lcmWith(PF1: PolyFactor, PF2: PolyFactor): PolyFactor {
|
|
126
|
+
|
|
127
|
+
const factors1 = keyFactors(PF1)
|
|
128
|
+
|
|
129
|
+
const factors2 = keyFactors(PF2)
|
|
130
|
+
|
|
131
|
+
const common = [...new Set([...Object.keys(factors1), ...Object.keys(factors2)])]
|
|
132
|
+
|
|
133
|
+
// Find the maximum power of the common factors
|
|
134
|
+
const factors = common.map(k => {
|
|
135
|
+
const power =
|
|
136
|
+
Object.hasOwn(factors1, k) ?
|
|
137
|
+
factors1[k].reduce((acc, f) => acc.add(f.power), new Fraction('0')) :
|
|
138
|
+
new Fraction(0)
|
|
139
|
+
const power2 = Object.hasOwn(factors2, k) ?
|
|
140
|
+
factors2[k].reduce((acc, f) => acc.add(f.power), new Fraction('0')) :
|
|
141
|
+
new Fraction(0)
|
|
142
|
+
return new Factor(k, Fraction.max(power, power2))
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
return new PolyFactor(...factors)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static gcd(...values: PolyFactor[]): PolyFactor {
|
|
149
|
+
if (values.length === 0) {
|
|
150
|
+
return new PolyFactor().one()
|
|
151
|
+
}
|
|
152
|
+
if (values.length === 1) {
|
|
153
|
+
return values[0]
|
|
154
|
+
}
|
|
155
|
+
if (values.length === 2) {
|
|
156
|
+
return PolyFactor.#gcdWith(values[0], values[1])
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// values is not undefined,
|
|
160
|
+
let PF = values[0]
|
|
161
|
+
values.shift()
|
|
162
|
+
values.forEach(value => PF = PolyFactor.#gcdWith(PF, value))
|
|
163
|
+
|
|
164
|
+
return PF
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
static lcm(...values: PolyFactor[]): PolyFactor {
|
|
168
|
+
if (values.length === 0) {
|
|
169
|
+
return new PolyFactor().one()
|
|
170
|
+
}
|
|
171
|
+
if (values.length === 1) {
|
|
172
|
+
return values[0]
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let PF = values[0]
|
|
176
|
+
values.shift()
|
|
177
|
+
values.forEach(value => PF = PolyFactor.#lcmWith(PF, value))
|
|
178
|
+
return PF
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
add(...values: PolyFactor[]): this {
|
|
182
|
+
// Adding two (or more) polyfactors:
|
|
183
|
+
// if both are numerators only, use the common polynom
|
|
184
|
+
// if there are denominators, multiply every polyfactors to match the lcm polyfactor.
|
|
185
|
+
|
|
186
|
+
const numerators: PolyFactor[] = [this.numerator, ...values.map(x => x.numerator)]
|
|
187
|
+
const denominators: PolyFactor[] = [this.denominator, ...values.map(x => x.denominator)]
|
|
188
|
+
|
|
189
|
+
let denominator: PolyFactor | undefined
|
|
190
|
+
if (denominators.some(d => d.factors.length > 0)) {
|
|
191
|
+
// At least one of the denominators is not empty.
|
|
192
|
+
const lcm = PolyFactor.lcm(...denominators)
|
|
193
|
+
|
|
194
|
+
// Multiply each numerators by the complementary.
|
|
195
|
+
numerators.forEach((n, index) => {
|
|
196
|
+
n.multiply(lcm.clone().divide(denominators[index]))
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// Set the common denominator to the lcm PolyFctor
|
|
200
|
+
denominator = lcm
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Now, every polyfactor should have a common denominator. Just add the numerators.
|
|
204
|
+
const gcd = PolyFactor.gcd(...numerators)
|
|
205
|
+
const remainingPolynom = new Polynom(0)
|
|
206
|
+
.add(...numerators.map(pf => {
|
|
207
|
+
return pf
|
|
208
|
+
.divide(gcd).reduce()
|
|
209
|
+
.develop() // should be a polyfactor with one factor, with a power of 1
|
|
210
|
+
.factors[0]
|
|
211
|
+
.polynom
|
|
212
|
+
})
|
|
213
|
+
).reduce()
|
|
214
|
+
|
|
215
|
+
this.#factors = [
|
|
216
|
+
...gcd.factors,
|
|
217
|
+
new Factor(remainingPolynom)
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
if (denominator) {
|
|
221
|
+
this.divide(denominator)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Remove all factors with a power of zero
|
|
225
|
+
this.#factors = this.#factors.filter(x => !x.power.isZero())
|
|
226
|
+
|
|
227
|
+
return this
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
get asPower(): this {
|
|
231
|
+
this.#displayMode = FACTOR_DISPLAY.POWER
|
|
232
|
+
return this
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
get asRoot(): this {
|
|
236
|
+
this.#displayMode = FACTOR_DISPLAY.ROOT
|
|
237
|
+
return this
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
degree(letter?: string): Fraction {
|
|
241
|
+
return this.#factors.reduce((acc, f) => acc.add(f.degree(letter)), new Fraction('0'))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
get denominator(): PolyFactor {
|
|
245
|
+
return new PolyFactor(...this.#factors
|
|
246
|
+
.filter(f => f.power.isNegative())
|
|
247
|
+
.map(f => f.clone().inverse())
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
derivative(): this {
|
|
252
|
+
// (fgh)' = f'gh+fg'h+fgh'
|
|
253
|
+
// dPF = [f'gh, fg'h, fgh']
|
|
254
|
+
const dPF: PolyFactor[] = []
|
|
255
|
+
|
|
256
|
+
const length = this.#factors.length
|
|
257
|
+
|
|
258
|
+
for (let i = 0; i < length; i++) {
|
|
259
|
+
// unchanged factors
|
|
260
|
+
const factors = this.#factors.slice()
|
|
261
|
+
// derivative factor
|
|
262
|
+
const derivativeFactor = factors.splice(i, 1)[0].derivative()
|
|
263
|
+
// Add the product of factors
|
|
264
|
+
dPF.push(
|
|
265
|
+
new PolyFactor(...factors, ...derivativeFactor))
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Reduce the polyFactors
|
|
269
|
+
dPF.forEach(pf => pf.reduce())
|
|
270
|
+
|
|
271
|
+
const first = dPF.shift()
|
|
272
|
+
if (first !== undefined) {
|
|
273
|
+
this.#factors = first.factors
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Add each factors together.
|
|
277
|
+
return this.add(...dPF)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
develop(): PolyFactor {
|
|
281
|
+
// Develop each factor and multiply them
|
|
282
|
+
const N = new Polynom('1')
|
|
283
|
+
const D = new Polynom('1')
|
|
284
|
+
|
|
285
|
+
this.numerator.factors.forEach(f => {
|
|
286
|
+
N.multiply(f.develop())
|
|
287
|
+
})
|
|
288
|
+
this.denominator.factors.forEach(f => {
|
|
289
|
+
D.multiply(f.develop())
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
return new PolyFactor().fromPolynom(N, D)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
divide(value: PolyFactor): this {
|
|
296
|
+
this.#factors = this.#factors.concat(value.clone().factors.map(f => f.inverse()))
|
|
297
|
+
return this
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
evaluate(values: InputValue<Fraction> | literalType<number | Fraction>, asNumeric?: boolean): number | Fraction {
|
|
301
|
+
if (asNumeric) {
|
|
302
|
+
return this.#factors
|
|
303
|
+
.reduce((acc, f) => acc * (f.evaluate(values, asNumeric) as number), 1)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return this.#factors
|
|
307
|
+
.reduce((acc, f) => acc.multiply(f.evaluate(values)), new Fraction('1'))
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
factorize(letter?: string): PolyFactor {
|
|
311
|
+
// Go through each factors.
|
|
312
|
+
// If it can be factorized, remove the factor (set its power to zero) and insert the new factors instead.
|
|
313
|
+
const newFactors: Factor[] = []
|
|
314
|
+
|
|
315
|
+
this.#factors.forEach(factor => {
|
|
316
|
+
const factors = factor.polynom.factorize(letter)
|
|
317
|
+
if (factors.length > 1) {
|
|
318
|
+
const pow = factor.power.clone()
|
|
319
|
+
newFactors.push(...factors.map(x => new Factor(x, pow)))
|
|
320
|
+
} else {
|
|
321
|
+
newFactors.push(factor.clone())
|
|
322
|
+
}
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
const result = new PolyFactor(...newFactors)
|
|
326
|
+
const numerator = result.numerator.reduce()
|
|
327
|
+
const denominator = result.denominator.reduce()
|
|
328
|
+
|
|
329
|
+
return numerator.divide(denominator)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
get factors(): Factor[] {
|
|
333
|
+
return this.#factors
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
set factors(value: Factor[]) {
|
|
337
|
+
this.#factors = value
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
fromPolynom(numerator: InputAlgebra<Polynom>, denominator?: InputAlgebra<Polynom>): this {
|
|
341
|
+
// fromPolynom loads the numerator and denominator as is, without factorizing !
|
|
342
|
+
// TODO: fromPolynom should parse the string if it's factorized: 3x(...)^3(..)^2(12x)
|
|
343
|
+
this.#factors = [new Factor(new Polynom(numerator))]
|
|
344
|
+
|
|
345
|
+
if (denominator) {
|
|
346
|
+
const polynom = new Polynom(denominator)
|
|
347
|
+
|
|
348
|
+
if (polynom.isOne()) return this
|
|
349
|
+
|
|
350
|
+
if (polynom.isZero()) throw new MathError("Cannot divide by zero")
|
|
351
|
+
|
|
352
|
+
this.#factors.push(new Factor(polynom, -1))
|
|
353
|
+
}
|
|
354
|
+
return this
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
fromString(value: string): this {
|
|
358
|
+
this.#factors = []
|
|
359
|
+
|
|
360
|
+
// Two cases :
|
|
361
|
+
// - either the string is given as a factorized string
|
|
362
|
+
// - or the string has something that prevents this => use fromPolynom
|
|
363
|
+
|
|
364
|
+
const [num, ...den] = splitIfOutsideParentheses(value, '/')
|
|
365
|
+
if(num==='') throw new ParseError('Parsing a PolyFactor from a string requires a numerator')
|
|
366
|
+
if(den.length>1) throw new ParseError('Parsing a PolyFactor from a string only allows max one signe "/"')
|
|
367
|
+
|
|
368
|
+
if(den.length===0) {
|
|
369
|
+
this.#factors = Factor.factorsFromString(stripParenthesis(num), true)
|
|
370
|
+
}else{
|
|
371
|
+
this.#factors = [
|
|
372
|
+
...Factor.factorsFromString(stripParenthesis(num), true),
|
|
373
|
+
...Factor.factorsFromString(stripParenthesis(den[0]), false),
|
|
374
|
+
]
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return this
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Get the roots of the PolyFactor.
|
|
382
|
+
*/
|
|
383
|
+
getRoots(): Solution[] {
|
|
384
|
+
return []
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
getZeroes(): Solution[] {
|
|
388
|
+
// Calculate the list of roots (ordered, unique)
|
|
389
|
+
const roots: Solution[] = ([] as Solution[])
|
|
390
|
+
.concat(...this.#factors.map(x => x.polynom.getZeroes()))
|
|
391
|
+
// .concat(...tos.map(x => x.roots))
|
|
392
|
+
|
|
393
|
+
// Sort the values.
|
|
394
|
+
roots.sort((a, b) => a.value - b.value)
|
|
395
|
+
// Remove duplicates.
|
|
396
|
+
return roots
|
|
397
|
+
.filter((value, index, self) =>
|
|
398
|
+
index === self.findIndex((t) =>
|
|
399
|
+
t.value === value.value
|
|
400
|
+
)
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
hasVariable(letter: string): boolean {
|
|
405
|
+
return this.#factors.some(f => f.hasVariable(letter))
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
inverse(): this {
|
|
409
|
+
this.#factors = this.#factors.map(f => f.inverse())
|
|
410
|
+
return this
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
isEqual(value: PolyFactor): boolean {
|
|
414
|
+
const gcd = PolyFactor.gcd(this, value)
|
|
415
|
+
|
|
416
|
+
const PF1 = this.clone().divide(gcd).reduce()
|
|
417
|
+
const PF2 = value.clone().divide(gcd).reduce()
|
|
418
|
+
|
|
419
|
+
return PF1.isOne() && PF2.isOne()
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
isOne(): boolean {
|
|
423
|
+
return this.#factors.every(f => f.isOne())
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
isZero(): boolean {
|
|
427
|
+
return this.#factors.every(f => f.isZero())
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
multiply(...values: (InputAlgebra<Polynom> | Factor |PolyFactor)[]): this {
|
|
431
|
+
values.forEach(value => {
|
|
432
|
+
const PF = new PolyFactor( value )
|
|
433
|
+
this.#factors = this.#factors.concat(PF.factors)
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
return this
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
get numerator(): PolyFactor {
|
|
440
|
+
return new PolyFactor(...this.#factors.filter(f => f.power.isPositive()))
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
one(): this {
|
|
444
|
+
this.#factors = [new Factor('1', '1')]
|
|
445
|
+
return this
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
opposite(): this {
|
|
449
|
+
// Add the -1 factor or remove if it exists
|
|
450
|
+
const index = this.#factors.findIndex(f => f.display === '(-1)')
|
|
451
|
+
|
|
452
|
+
if (index >= 0) {
|
|
453
|
+
this.#factors.splice(index, 1)
|
|
454
|
+
} else {
|
|
455
|
+
this.#factors.push(new Factor('-1', '1'))
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return this
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
pow(value: number | Fraction): this {
|
|
462
|
+
this.#factors = this.#factors.map(f => f.pow(value))
|
|
463
|
+
return this
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
primitive(): PolyFactor {
|
|
467
|
+
throw new NotImplementedError("Method not implemented.")
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
reduce(): this {
|
|
471
|
+
// Regroup the factors by their base
|
|
472
|
+
const factors = keyFactors(this)
|
|
473
|
+
|
|
474
|
+
// Multiply the factors of the same base
|
|
475
|
+
this.#factors = Object.values(factors)
|
|
476
|
+
.map(f => {
|
|
477
|
+
const base = f[0].polynom
|
|
478
|
+
const power = f.reduce((acc, f) => acc.add(f.power), new Fraction('0'))
|
|
479
|
+
|
|
480
|
+
return new Factor(base, power.reduce())
|
|
481
|
+
})
|
|
482
|
+
.filter(f => !f.power.isZero())
|
|
483
|
+
|
|
484
|
+
// Everything is reduced - merge all monomial factors together.
|
|
485
|
+
const numfactor = new Factor(1)
|
|
486
|
+
const denfactor = new Factor(1)
|
|
487
|
+
const monomials = this.#factors.filter(x=>x.polynom.monoms.length===1 && x.power.isRelative())
|
|
488
|
+
if(monomials.length>0){
|
|
489
|
+
monomials.forEach(m=> {
|
|
490
|
+
if(m.power.isPositive()){
|
|
491
|
+
numfactor.multiply(new Factor(m.polynom.clone().pow(m.power.value)))
|
|
492
|
+
}else{
|
|
493
|
+
denfactor.multiply(new Factor(m.polynom.clone().pow(-m.power.value)))
|
|
494
|
+
}
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
this.#factors = this.#factors.filter(x=>!(x.polynom.monoms.length===1 && x.power.isRelative()))
|
|
498
|
+
if (!denfactor.polynom.isOne()){this.#factors.push(denfactor.inverse())}
|
|
499
|
+
if (!numfactor.polynom.isOne()){this.#factors.push(numfactor)}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return this
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
root(value: number): this {
|
|
506
|
+
this.#factors = this.#factors.map(f => f.root(value))
|
|
507
|
+
return this
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Reoarder the factors using :
|
|
512
|
+
* 1. number of monoms
|
|
513
|
+
* 2. degree of polynom
|
|
514
|
+
* 3. power of polyfactor
|
|
515
|
+
*/
|
|
516
|
+
sort(letter?: string): this {
|
|
517
|
+
// Sort each polynom
|
|
518
|
+
this.#factors.forEach(f=>f.polynom.reorder(letter))
|
|
519
|
+
|
|
520
|
+
this.#factors.sort((a, b) => {
|
|
521
|
+
// If the compare powers are opposite, the negative power goes to the end.
|
|
522
|
+
const aPower = a.power.value
|
|
523
|
+
const bPower = b.power.value
|
|
524
|
+
if (aPower * bPower < 0) {
|
|
525
|
+
return -aPower
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Monom length
|
|
529
|
+
const aLength = a.polynom.monoms.length
|
|
530
|
+
const bLength = b.polynom.monoms.length
|
|
531
|
+
if (aLength !== bLength) {
|
|
532
|
+
return aLength - bLength
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// The monom length are the same, check the polynom degree.
|
|
536
|
+
const aDegree = a.polynom.degree(letter).value
|
|
537
|
+
const bDegree = b.polynom.degree(letter).value
|
|
538
|
+
if (aDegree !== bDegree) {
|
|
539
|
+
return aDegree - bDegree
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// The power of the PolyFactor
|
|
543
|
+
if (aPower !== bPower) {
|
|
544
|
+
return aPower - bPower
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// It the monoms length are two AND of degree one, sort by the zero.
|
|
548
|
+
if(a.polynom.degree(letter).isOne() && b.polynom.degree(letter).isOne()){
|
|
549
|
+
const aSol = a.polynom.monoms[1].coefficient.clone().opposite().divide(a.polynom.monoms[0].coefficient).value
|
|
550
|
+
const bSol = b.polynom.monoms[1].coefficient.clone().opposite().divide(b.polynom.monoms[0].coefficient).value
|
|
551
|
+
|
|
552
|
+
return aSol - bSol
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return a.degree().isLeq(b.degree()) ? -1 : 1
|
|
556
|
+
})
|
|
557
|
+
|
|
558
|
+
return this
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
sqrt(): this {
|
|
562
|
+
this.#factors = this.#factors.map(f => f.sqrt())
|
|
563
|
+
return this
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
subtract(...values: PolyFactor[]): this {
|
|
567
|
+
return this.add(...values.map(f => f.opposite()))
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
tableOfSigns(): POLYFACTOR_TABLE_OF_SIGNS {
|
|
571
|
+
// Calculate the table of signs for each factor
|
|
572
|
+
const roots = this.getZeroes()
|
|
573
|
+
const roots_key = roots.map(x => x.value)
|
|
574
|
+
|
|
575
|
+
// Get the table of signs of every factors
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
// These signs are NOT aligned
|
|
579
|
+
const factors: FACTOR_TABLE_OF_SIGNS[] = this.factorize().factors
|
|
580
|
+
.map(factor => {
|
|
581
|
+
return {factor: new Factor(factor), ...factor.tableOfSigns()}
|
|
582
|
+
})
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
// Build the table of signs with extra roots for each factors.
|
|
586
|
+
factors.forEach(item => {
|
|
587
|
+
// Create the new signs row
|
|
588
|
+
const empty_signs: TABLE_OF_SIGNS_VALUES[] = new Array(2 * roots.length + 1).fill('') as unknown as TABLE_OF_SIGNS_VALUES[]
|
|
589
|
+
|
|
590
|
+
let sign = item.signs.shift() as unknown as TABLE_OF_SIGNS_VALUES
|
|
591
|
+
let root = item.roots.shift()
|
|
592
|
+
|
|
593
|
+
const aligned_signs = empty_signs.map((_sign, index) => {
|
|
594
|
+
if (index % 2 === 0) {
|
|
595
|
+
return sign
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// The sign for this indexed root is a t(ab)
|
|
599
|
+
if (root?.value !== roots_key[(index - 1) / 2]) {
|
|
600
|
+
return 't'
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// The indexed root is the new root
|
|
604
|
+
const rootSign = item.signs.shift() as unknown as TABLE_OF_SIGNS_VALUES
|
|
605
|
+
|
|
606
|
+
// Make the new signs.
|
|
607
|
+
sign = item.signs.shift() as unknown as TABLE_OF_SIGNS_VALUES
|
|
608
|
+
root = item.roots.shift()
|
|
609
|
+
return rootSign
|
|
610
|
+
})
|
|
611
|
+
|
|
612
|
+
// Set the roots for this item to all roots
|
|
613
|
+
item.roots = roots
|
|
614
|
+
item.signs = aligned_signs
|
|
615
|
+
})
|
|
616
|
+
|
|
617
|
+
// Build the table of signs with extra roots : reault line
|
|
618
|
+
const signs: TABLE_OF_SIGNS_VALUES[] = factors
|
|
619
|
+
.map((item) => [...item.signs])
|
|
620
|
+
.reduce<TABLE_OF_SIGNS_VALUES[]>((a, b) => {
|
|
621
|
+
if (a.length === 0) {
|
|
622
|
+
return b
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// a and b are "not aligned"
|
|
626
|
+
b.forEach((value, index) => {
|
|
627
|
+
// Case of a zero, invalid or tab value
|
|
628
|
+
// tab < zero < defence
|
|
629
|
+
switch (value) {
|
|
630
|
+
case "d":
|
|
631
|
+
a[index] = "d"
|
|
632
|
+
break
|
|
633
|
+
case "z":
|
|
634
|
+
a[index] = a[index] === "d" ? "d" : "z"
|
|
635
|
+
break
|
|
636
|
+
case "h":
|
|
637
|
+
a[index] = "h"
|
|
638
|
+
break
|
|
639
|
+
case "-":
|
|
640
|
+
a[index] = a[index] === "h" ? "h" : a[index] === "-" ? "+" : "-"
|
|
641
|
+
break
|
|
642
|
+
}
|
|
643
|
+
})
|
|
644
|
+
|
|
645
|
+
return a
|
|
646
|
+
}, [])
|
|
647
|
+
|
|
648
|
+
return {signs, roots, factors}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
get variables(): string[] {
|
|
652
|
+
return this.#factors
|
|
653
|
+
.reduce((acc: string[], f: Factor) => acc.concat(f.variables), [])
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
zero(): this {
|
|
657
|
+
this.#factors = [new Factor('0', '1')]
|
|
658
|
+
return this
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
#extractNumeratorAndDenominator() {
|
|
662
|
+
let num: Factor[],
|
|
663
|
+
den: Factor[] = []
|
|
664
|
+
|
|
665
|
+
if (this.#displayMode === FACTOR_DISPLAY.ROOT) {
|
|
666
|
+
// the power are positive integers
|
|
667
|
+
num = this.numerator.factors
|
|
668
|
+
den = this.denominator.factors
|
|
669
|
+
} else {
|
|
670
|
+
num = this.#factors
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// There is no factor
|
|
674
|
+
if (num.length === 0) {
|
|
675
|
+
num = [new Factor('1')]
|
|
676
|
+
}
|
|
677
|
+
return {num, den}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function keyFactors(value: PolyFactor): Record<string, Factor[]> {
|
|
683
|
+
const k_numerator = new Fraction().one()
|
|
684
|
+
const k_denominator = new Fraction().one()
|
|
685
|
+
|
|
686
|
+
const kF = value.factors
|
|
687
|
+
.reduce((acc: Record<string, Factor[]>, f) => {
|
|
688
|
+
// It's only a value (without roots
|
|
689
|
+
// TODO: implement reduce root numeric.
|
|
690
|
+
if (f.polynom.degree().isZero() && f.power.isRelative()) {
|
|
691
|
+
const value = f.polynom.monoms[0].coefficient.pow(f.power.clone().abs())
|
|
692
|
+
|
|
693
|
+
if (f.power.isPositive()) {
|
|
694
|
+
k_numerator.multiply(value)
|
|
695
|
+
} else {
|
|
696
|
+
k_denominator.multiply(value)
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
return acc
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// It's a polynom
|
|
703
|
+
const base = f.polynom.display
|
|
704
|
+
if (Object.hasOwn(acc, base)) {
|
|
705
|
+
acc[base].push(f)
|
|
706
|
+
} else {
|
|
707
|
+
acc[base] = [f]
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
return acc
|
|
711
|
+
}, {})
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
const {numerator, denominator} = k_numerator.divide(k_denominator).reduce()
|
|
715
|
+
if(numerator!==1){
|
|
716
|
+
kF[numerator.toString()] = [new Factor(numerator, 1)]
|
|
717
|
+
}
|
|
718
|
+
if(denominator!==1){
|
|
719
|
+
kF[denominator.toString()] = [new Factor(denominator, -1)]
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
return kF
|
|
723
|
+
}
|
|
724
|
+
|