pimath 0.1.40 → 0.2.1
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 +3106 -2873
- package/dist/pimath.js.map +1 -1
- package/package.json +13 -11
- package/src/algebra/equation.ts +113 -111
- package/src/algebra/equationSolver.ts +69 -120
- package/src/algebra/factor.ts +6 -7
- package/src/algebra/linearSystem.ts +97 -46
- package/src/algebra/logicalset.ts +51 -52
- package/src/algebra/monom.ts +23 -61
- package/src/algebra/operations.ts +0 -1
- package/src/algebra/polyFactor.ts +5 -5
- package/src/algebra/polynom.ts +69 -216
- package/src/analyze/index.ts +4 -0
- package/src/analyze/solution.ts +92 -29
- package/src/analyze/tableOfSigns.ts +1 -1
- package/src/coefficients/fraction.ts +189 -149
- package/src/coefficients/index.ts +1 -1
- package/src/coefficients/root.ts +66 -19
- package/src/geometry/TupleN.ts +128 -0
- package/src/geometry/circle.ts +308 -238
- package/src/geometry/geomMath.ts +4 -3
- package/src/geometry/index.ts +1 -0
- package/src/geometry/line.ts +221 -245
- package/src/geometry/line3.ts +78 -73
- package/src/geometry/plane3.ts +64 -55
- package/src/geometry/point.ts +57 -19
- package/src/geometry/triangle.ts +376 -248
- package/src/geometry/vector.ts +113 -229
- package/src/index.ts +13 -12
- package/src/numeric.ts +6 -9
- package/src/pimath.interface.ts +30 -28
- package/src/randomization/algebra/rndPolynom.ts +29 -15
- package/src/randomization/coefficient/rndFraction.ts +3 -3
- package/src/randomization/geometry/rndLine.ts +8 -10
- package/src/randomization/random.ts +11 -13
- package/src/randomization/rndTypes.ts +16 -12
- package/types/algebra/equation.d.ts +18 -17
- package/types/algebra/equation.d.ts.map +1 -1
- package/types/algebra/equationSolver.d.ts +5 -4
- package/types/algebra/equationSolver.d.ts.map +1 -1
- package/types/algebra/factor.d.ts +1 -1
- package/types/algebra/factor.d.ts.map +1 -1
- package/types/algebra/linearSystem.d.ts +23 -6
- package/types/algebra/linearSystem.d.ts.map +1 -1
- package/types/algebra/logicalset.d.ts +1 -1
- package/types/algebra/logicalset.d.ts.map +1 -1
- package/types/algebra/monom.d.ts +1 -6
- package/types/algebra/monom.d.ts.map +1 -1
- package/types/algebra/operations.d.ts.map +1 -1
- package/types/algebra/polyFactor.d.ts +4 -4
- package/types/algebra/polyFactor.d.ts.map +1 -1
- package/types/algebra/polynom.d.ts +10 -7
- package/types/algebra/polynom.d.ts.map +1 -1
- package/types/analyze/index.d.ts +2 -0
- package/types/analyze/index.d.ts.map +1 -0
- package/types/analyze/solution.d.ts +14 -8
- package/types/analyze/solution.d.ts.map +1 -1
- package/types/coefficients/fraction.d.ts +14 -12
- package/types/coefficients/fraction.d.ts.map +1 -1
- package/types/coefficients/index.d.ts +1 -1
- package/types/coefficients/index.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/TupleAbstract.d.ts +22 -0
- package/types/geometry/TupleAbstract.d.ts.map +1 -0
- package/types/geometry/TupleN.d.ts +24 -0
- package/types/geometry/TupleN.d.ts.map +1 -0
- package/types/geometry/circle.d.ts +26 -17
- package/types/geometry/circle.d.ts.map +1 -1
- package/types/geometry/geomMath.d.ts +2 -1
- package/types/geometry/geomMath.d.ts.map +1 -1
- package/types/geometry/index.d.ts.map +1 -1
- package/types/geometry/line.d.ts +21 -30
- package/types/geometry/line.d.ts.map +1 -1
- package/types/geometry/line3.d.ts +19 -19
- package/types/geometry/line3.d.ts.map +1 -1
- package/types/geometry/matrix.d.ts +11 -11
- package/types/geometry/plane3.d.ts +10 -10
- package/types/geometry/plane3.d.ts.map +1 -1
- package/types/geometry/point.d.ts +11 -6
- package/types/geometry/point.d.ts.map +1 -1
- package/types/geometry/triangle.d.ts +68 -23
- package/types/geometry/triangle.d.ts.map +1 -1
- package/types/geometry/vector.d.ts +24 -44
- package/types/geometry/vector.d.ts.map +1 -1
- package/types/index.d.ts +5 -4
- package/types/index.d.ts.map +1 -1
- package/types/numeric.d.ts.map +1 -1
- package/types/pimath.interface.d.ts +18 -24
- package/types/pimath.interface.d.ts.map +1 -1
- package/types/randomization/algebra/rndPolynom.d.ts.map +1 -1
- package/types/randomization/coefficient/rndFraction.d.ts +1 -1
- package/types/randomization/coefficient/rndFraction.d.ts.map +1 -1
- package/types/randomization/geometry/rndLine.d.ts.map +1 -1
- package/types/randomization/random.d.ts +3 -2
- package/types/randomization/random.d.ts.map +1 -1
- package/types/randomization/rndTypes.d.ts +15 -10
- package/types/randomization/rndTypes.d.ts.map +1 -1
- package/src/coefficients/nthRoot.ts +0 -149
package/src/algebra/polynom.ts
CHANGED
|
@@ -9,7 +9,6 @@ import type {
|
|
|
9
9
|
InputAlgebra,
|
|
10
10
|
InputValue,
|
|
11
11
|
IPiMathObject,
|
|
12
|
-
ISolution,
|
|
13
12
|
literalType,
|
|
14
13
|
TABLE_OF_SIGNS,
|
|
15
14
|
TABLE_OF_SIGNS_VALUES
|
|
@@ -20,6 +19,7 @@ import {EquationSolver} from './equationSolver'
|
|
|
20
19
|
import {Monom} from './monom'
|
|
21
20
|
import {replace_in_array} from "../helpers"
|
|
22
21
|
import {operation_pow} from "./operations"
|
|
22
|
+
import {Solution} from "../analyze/solution"
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
export type PolynomParsingType = InputValue<Polynom> | Monom
|
|
@@ -43,7 +43,7 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
43
43
|
#defaultVariable = 'x'
|
|
44
44
|
#factors: Polynom[]
|
|
45
45
|
#monoms: Monom[]
|
|
46
|
-
#roots:
|
|
46
|
+
#roots: Solution[]
|
|
47
47
|
#rootsCache = false
|
|
48
48
|
|
|
49
49
|
constructor(value: InputValue<Fraction>)
|
|
@@ -63,6 +63,7 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
63
63
|
return this
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
|
|
66
67
|
/**
|
|
67
68
|
* Parse a string to a polynom.
|
|
68
69
|
* @param inputStr
|
|
@@ -120,6 +121,16 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
120
121
|
return this.#genDisplay()
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
static xMultiply(...polynoms: InputValue<Polynom>[]): Polynom {
|
|
125
|
+
const result = new Polynom().one()
|
|
126
|
+
|
|
127
|
+
polynoms.forEach(P => {
|
|
128
|
+
result.multiply(P)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
return result
|
|
132
|
+
}
|
|
133
|
+
|
|
123
134
|
public add = (...values: InputAlgebra<Polynom>[]): Polynom => {
|
|
124
135
|
|
|
125
136
|
for (const value of values) {
|
|
@@ -281,98 +292,62 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
281
292
|
/**
|
|
282
293
|
* Factorize a polynom and store the best results in factors.
|
|
283
294
|
* @param letter
|
|
295
|
+
* TODO: Handle other letter than 'x'.
|
|
284
296
|
*/
|
|
297
|
+
public factorize(letter?: string): Polynom[] {
|
|
298
|
+
this.#factors = []
|
|
285
299
|
|
|
286
|
-
// REFACTOR: duplicate code with equationSolver.
|
|
287
|
-
public factorize = (letter?: string): Polynom[] => {
|
|
288
|
-
let factors: Polynom[] = []
|
|
289
300
|
let P = this.clone().reorder()
|
|
290
301
|
|
|
291
302
|
// Extract the common monom
|
|
292
303
|
// 2x^3+6x^2 => 2x^2
|
|
293
304
|
const M = P.commonMonom()
|
|
294
|
-
// If the polynom starts with a negative monom, factorize it.
|
|
295
|
-
if (P.monomByDegree().coefficient.isStrictlyNegative() && M.coefficient.isStrictlyPositive() && !M.isOne()) {
|
|
296
|
-
M.opposite()
|
|
297
|
-
}
|
|
298
305
|
|
|
306
|
+
// If the polynom starts with a negative monom, factorize it.
|
|
307
|
+
if (P.monomByDegree().coefficient.isStrictlyNegative()) M.opposite()
|
|
299
308
|
|
|
300
309
|
if (!M.isOne()) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
P = P.euclidean(tempPolynom).quotient
|
|
310
|
+
this.#factors.push(new Polynom(M))
|
|
311
|
+
P = P.euclidean(this.#factors[0]).quotient
|
|
304
312
|
}
|
|
305
313
|
|
|
306
|
-
|
|
307
|
-
let securityLoop = P.degree().clone().multiply(2).value,
|
|
308
|
-
maxDegree = 1
|
|
309
|
-
while (securityLoop >= 0) {
|
|
310
|
-
securityLoop--
|
|
311
|
-
if (P.monoms.length < 2) {
|
|
312
|
-
// The polynom has only one monom => 7x^2
|
|
313
|
-
// No need to continue.
|
|
314
|
-
if (!P.isOne()) {
|
|
315
|
-
factors.push(P.clone())
|
|
316
|
-
P.one()
|
|
317
|
-
}
|
|
318
|
-
break
|
|
319
|
-
} else if (P.degree(letter).isOne()) {
|
|
320
|
-
// The polynom is a first degree polynom => 3x-5
|
|
321
|
-
// No need to continue
|
|
322
|
-
factors.push(P.clone())
|
|
323
|
-
P.one()
|
|
324
|
-
break
|
|
325
|
-
} else {
|
|
326
|
-
// Create the list of all "potential" polynom dividers.
|
|
327
|
-
let allDividers: Polynom[] = this.#getAllPotentialFactors(P, maxDegree, letter ?? 'x')
|
|
328
|
-
maxDegree = P.degree(letter).value
|
|
329
|
-
|
|
330
|
-
// Actually: 100ms
|
|
331
|
-
while (allDividers.length > 0) {
|
|
332
|
-
const div = allDividers[0]
|
|
333
|
-
|
|
334
|
-
if (!P.isDividableBy(div))
|
|
335
|
-
// Not dividable. Remove it from the list
|
|
336
|
-
{
|
|
337
|
-
allDividers.shift()
|
|
338
|
-
} else {
|
|
339
|
-
// It's dividable - so make the division
|
|
340
|
-
const result = P.euclidean(div)
|
|
341
|
-
|
|
342
|
-
// Add the factor
|
|
343
|
-
factors.push(div)
|
|
344
|
-
|
|
345
|
-
// As it's dividable, get the quotient.
|
|
346
|
-
P = result.quotient.clone()
|
|
347
|
-
|
|
348
|
-
// filter all dividers that are no more suitable.
|
|
349
|
-
allDividers = allDividers.filter(x => {
|
|
350
|
-
const pX = P.monoms[0],
|
|
351
|
-
pC = P.monoms[P.monoms.length - 1],
|
|
352
|
-
dX = x.monoms[0],
|
|
353
|
-
dC = x.monoms[x.monoms.length - 1]
|
|
314
|
+
const solutions = new EquationSolver(P).solve()
|
|
354
315
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
316
|
+
if (solutions.length === 0) {
|
|
317
|
+
this.#factors = [this.clone()]
|
|
318
|
+
return this.#factors
|
|
319
|
+
}
|
|
359
320
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
321
|
+
solutions.forEach(sol => {
|
|
322
|
+
if (sol.exact && sol.root.isZero()) {
|
|
323
|
+
for (let i = 0; i < sol.count; i++) {
|
|
324
|
+
if (sol.fraction.isRational()) {
|
|
325
|
+
this.#factors.push(new Polynom().fromCoefficients(sol.fraction.denominator, -sol.fraction.numerator))
|
|
326
|
+
} else {
|
|
327
|
+
this.#factors.push(new Polynom().fromCoefficients(1, sol.fraction.clone().opposite()))
|
|
363
328
|
}
|
|
364
329
|
}
|
|
365
330
|
}
|
|
366
|
-
}
|
|
331
|
+
})
|
|
367
332
|
|
|
368
|
-
//
|
|
369
|
-
|
|
370
|
-
|
|
333
|
+
// Check if we have all factors.
|
|
334
|
+
const fDegrees = this.#factors
|
|
335
|
+
.map(f => f.degree().value)
|
|
336
|
+
.reduce((a, b) => a + b, 0)
|
|
337
|
+
|
|
338
|
+
if (fDegrees < this.degree().value) {
|
|
339
|
+
// missing polynom.
|
|
340
|
+
const fPolynom = Polynom.xMultiply(...this.#factors)
|
|
341
|
+
this.#factors.push(this.clone().divide(fPolynom))
|
|
371
342
|
}
|
|
372
343
|
|
|
344
|
+
return this.#factors
|
|
345
|
+
}
|
|
373
346
|
|
|
374
|
-
|
|
375
|
-
this.#factors
|
|
347
|
+
get factors(): Polynom[] {
|
|
348
|
+
if (this.#factors.length === 0 && !this.isZero()) {
|
|
349
|
+
return this.factorize()
|
|
350
|
+
}
|
|
376
351
|
|
|
377
352
|
return this.#factors
|
|
378
353
|
}
|
|
@@ -435,7 +410,7 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
435
410
|
return numerators
|
|
436
411
|
}
|
|
437
412
|
|
|
438
|
-
public getZeroes = ():
|
|
413
|
+
public getZeroes = (): Solution[] => {
|
|
439
414
|
if (this.degree().isZero()) {
|
|
440
415
|
return []
|
|
441
416
|
}
|
|
@@ -499,8 +474,8 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
499
474
|
if (div.degree().isOne()) {
|
|
500
475
|
const zero = div.getZeroes()[0]
|
|
501
476
|
|
|
502
|
-
if (zero.exact
|
|
503
|
-
return (this.evaluate(zero.
|
|
477
|
+
if (zero.exact) {
|
|
478
|
+
return (this.evaluate(zero.fraction) as Fraction).isZero()
|
|
504
479
|
} else {
|
|
505
480
|
return false
|
|
506
481
|
}
|
|
@@ -528,30 +503,6 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
528
503
|
return this.#compare(P.clone().opposite(), '=')
|
|
529
504
|
}
|
|
530
505
|
|
|
531
|
-
public isReduced = (polynomString: string): boolean => {
|
|
532
|
-
// The polynom must be developed to be reduced.
|
|
533
|
-
if (!this.isDeveloped(polynomString)) {
|
|
534
|
-
return false
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
const P = new Polynom(polynomString)
|
|
539
|
-
if (P.monoms.length > this.monoms.length) {
|
|
540
|
-
return false
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
// TODO: Not sure the reduced system checking is working properly !
|
|
545
|
-
for (const m of P.monoms) {
|
|
546
|
-
if (!m.coefficient.isReduced()) {
|
|
547
|
-
return false
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
return false
|
|
553
|
-
}
|
|
554
|
-
|
|
555
506
|
public isSameAs = (P: Polynom): boolean => {
|
|
556
507
|
return this.#compare(P, 'same')
|
|
557
508
|
}
|
|
@@ -684,26 +635,31 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
684
635
|
|
|
685
636
|
if (value instanceof Polynom) {
|
|
686
637
|
return this.#multiplyByPolynom(value)
|
|
687
|
-
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (value instanceof Fraction) {
|
|
688
641
|
return this.#multiplyByFraction(value)
|
|
689
|
-
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (value instanceof Monom) {
|
|
690
645
|
return this.#multiplyByMonom(value)
|
|
691
|
-
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
if (Number.isSafeInteger(value) && typeof value === 'number') {
|
|
692
649
|
return this.#multiplyByInteger(value)
|
|
693
|
-
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
if (typeof value === 'string') {
|
|
694
653
|
try {
|
|
695
654
|
const k = new Fraction(value)
|
|
696
655
|
return this.#multiplyByFraction(k)
|
|
697
656
|
} catch {
|
|
698
657
|
throw new Error('Cannot multiply by this value.')
|
|
699
658
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
659
|
}
|
|
703
660
|
|
|
704
|
-
|
|
705
661
|
// Something went wrong...
|
|
706
|
-
throw new Error(
|
|
662
|
+
throw new Error(`Cannot multiply by this value: ${value as unknown as string}`)
|
|
707
663
|
}
|
|
708
664
|
|
|
709
665
|
public get numberOfVars(): number {
|
|
@@ -850,11 +806,11 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
850
806
|
throw new Error('Cannot take the root from a polynom')
|
|
851
807
|
}
|
|
852
808
|
|
|
853
|
-
get roots():
|
|
809
|
+
get roots(): Solution[] {
|
|
854
810
|
return this.#rootsCache ? this.#roots : this.getZeroes()
|
|
855
811
|
}
|
|
856
812
|
|
|
857
|
-
set roots(value:
|
|
813
|
+
set roots(value: Solution[]) {
|
|
858
814
|
this.#rootsCache = true
|
|
859
815
|
this.#roots = value
|
|
860
816
|
}
|
|
@@ -888,7 +844,7 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
888
844
|
// returns ['+-', 'd|t|z', '+-']...
|
|
889
845
|
|
|
890
846
|
// global roots from eventually Polyfactor. Allows to add "extra column".
|
|
891
|
-
const roots:
|
|
847
|
+
const roots: Solution[] = this.roots
|
|
892
848
|
|
|
893
849
|
// Build the table os sign length and default values
|
|
894
850
|
// The signs looks like: ['+', 't', '+', 't', '+', 't', '+']
|
|
@@ -962,7 +918,7 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
962
918
|
return this
|
|
963
919
|
}
|
|
964
920
|
|
|
965
|
-
public get zeroes():
|
|
921
|
+
public get zeroes(): Solution[] {
|
|
966
922
|
return this.getZeroes()
|
|
967
923
|
}
|
|
968
924
|
|
|
@@ -1025,110 +981,6 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
1025
981
|
return r
|
|
1026
982
|
}
|
|
1027
983
|
|
|
1028
|
-
#factorize2ndDegree = (letter: string): Polynom[] => {
|
|
1029
|
-
let P1: Polynom, P2: Polynom,
|
|
1030
|
-
a, b, c, delta, x1, x2, factor
|
|
1031
|
-
|
|
1032
|
-
// One variable only
|
|
1033
|
-
if (this.numberOfVars === 1) {
|
|
1034
|
-
a = this.monomByDegree(2, letter).coefficient
|
|
1035
|
-
b = this.monomByDegree(1, letter).coefficient
|
|
1036
|
-
c = this.monomByDegree(0, letter).coefficient
|
|
1037
|
-
delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4))
|
|
1038
|
-
|
|
1039
|
-
if (delta.isZero()) {
|
|
1040
|
-
x1 = b.clone().opposite().divide(a.clone().multiply(2))
|
|
1041
|
-
P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
|
|
1042
|
-
P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
|
|
1043
|
-
factor = a.divide(x1.denominator).divide(x1.denominator)
|
|
1044
|
-
|
|
1045
|
-
if (!factor.isOne()) {
|
|
1046
|
-
return [new Polynom(factor.display), P1, P2]
|
|
1047
|
-
} else {
|
|
1048
|
-
return [P1, P2]
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
} else if (delta.isPositive() && delta.isSquare()) {
|
|
1052
|
-
x1 = b.clone().opposite()
|
|
1053
|
-
.add(delta.clone().sqrt())
|
|
1054
|
-
.divide(a.clone().multiply(2))
|
|
1055
|
-
x2 = b.clone().opposite()
|
|
1056
|
-
.subtract(delta.clone().sqrt())
|
|
1057
|
-
.divide(a.clone().multiply(2))
|
|
1058
|
-
|
|
1059
|
-
// (2x+5)(3x-2)
|
|
1060
|
-
// 6x^2+11x-10
|
|
1061
|
-
// a = 6, b = 11, c = -10
|
|
1062
|
-
// delta = 121-4*6*(-10) = 361= 19^2
|
|
1063
|
-
// x1 = (-11 + 19) / 12 = 8/12 = 2/3
|
|
1064
|
-
// x2 = (-11 - 19) / 12 = -30/12 = -5/2
|
|
1065
|
-
factor = a.divide(x1.denominator).divide(x2.denominator)
|
|
1066
|
-
if (factor.isOne()) {
|
|
1067
|
-
return [
|
|
1068
|
-
new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
|
|
1069
|
-
new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
|
|
1070
|
-
]
|
|
1071
|
-
} else {
|
|
1072
|
-
return [
|
|
1073
|
-
new Polynom(factor.display),
|
|
1074
|
-
new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
|
|
1075
|
-
new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
|
|
1076
|
-
]
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
} else
|
|
1081
|
-
// No solution possible - return the complete value.
|
|
1082
|
-
{
|
|
1083
|
-
return [this.clone()]
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
} else {
|
|
1087
|
-
// If multiple variables, only handle perfect squares...
|
|
1088
|
-
a = this.monomByDegree(2, letter)
|
|
1089
|
-
b = this.monomByDegree(1, letter)
|
|
1090
|
-
c = this.monomByDegree(0, letter)
|
|
1091
|
-
|
|
1092
|
-
if (a.isLiteralSquare() && c.isLiteralSquare())
|
|
1093
|
-
// Check the middle item is same as...
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
{
|
|
1097
|
-
if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
|
|
1098
|
-
// Determine if the coefficient values matches.
|
|
1099
|
-
|
|
1100
|
-
// Search 4 values (r, s, t, u) that matches:
|
|
1101
|
-
// (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
|
|
1102
|
-
|
|
1103
|
-
const xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient)
|
|
1104
|
-
const xFactors = xPolynom.#factorize2ndDegree('x')
|
|
1105
|
-
|
|
1106
|
-
const factors = []
|
|
1107
|
-
let xyzPolynom: Polynom
|
|
1108
|
-
|
|
1109
|
-
if (xFactors.length >= 2) {
|
|
1110
|
-
for (const p of xFactors) {
|
|
1111
|
-
if (p.degree().isZero()) {
|
|
1112
|
-
factors.push(p.clone())
|
|
1113
|
-
} else {
|
|
1114
|
-
xyzPolynom = p.clone()
|
|
1115
|
-
xyzPolynom.monoms[0].literal = a.literalSqrt
|
|
1116
|
-
xyzPolynom.monoms[1].literal = c.literalSqrt
|
|
1117
|
-
factors.push(xyzPolynom.clone())
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
return factors
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
return [this.clone()]
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
984
|
#genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean, withAllMultiplicationSign?: boolean): string => {
|
|
1133
985
|
let P = ''
|
|
1134
986
|
|
|
@@ -1391,4 +1243,5 @@ export class Polynom implements IPiMathObject<Polynom>,
|
|
|
1391
1243
|
|
|
1392
1244
|
}
|
|
1393
1245
|
|
|
1246
|
+
|
|
1394
1247
|
}
|
package/src/analyze/solution.ts
CHANGED
|
@@ -1,53 +1,86 @@
|
|
|
1
|
-
// TODO: remplacer ISolution par Solution, qui sera plus robuste et extensible
|
|
2
|
-
|
|
3
1
|
import type {InputValue} from "../pimath.interface"
|
|
4
2
|
import {Fraction} from "../coefficients"
|
|
3
|
+
import {Root} from "../coefficients/root"
|
|
5
4
|
|
|
6
5
|
export class Solution {
|
|
7
|
-
#
|
|
6
|
+
#count: number
|
|
7
|
+
#display: string | null
|
|
8
8
|
#exact: boolean
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
#fraction: Fraction
|
|
10
|
+
#root: Root
|
|
11
|
+
#tex: string | null
|
|
11
12
|
#variable: string
|
|
12
13
|
|
|
13
14
|
constructor() {
|
|
14
15
|
this.#variable = 'x'
|
|
15
16
|
this.#exact = false
|
|
16
|
-
this.#isZero = true
|
|
17
17
|
|
|
18
|
-
this.#display =
|
|
19
|
-
this.#tex =
|
|
18
|
+
this.#display = null
|
|
19
|
+
this.#tex = null
|
|
20
|
+
|
|
21
|
+
this.#fraction = new Fraction().zero()
|
|
22
|
+
this.#root = new Root()
|
|
23
|
+
this.#count = 1
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
get tex(): string {
|
|
23
|
-
return this.#tex
|
|
27
|
+
if (this.#tex) return this.#tex
|
|
28
|
+
|
|
29
|
+
if (this.#root.isZero()) return this.#fraction.tex
|
|
30
|
+
|
|
31
|
+
if (this.#fraction.isZero()) return this.#root.tex
|
|
32
|
+
|
|
33
|
+
const [f] = Fraction.toSameDenominateur(this.#fraction, this.#root.factor)
|
|
34
|
+
|
|
35
|
+
const R = this.#root.clone().multiply(f.denominator).reduce()
|
|
36
|
+
const num = `${f.numerator} ${R.withSign.tex}`
|
|
37
|
+
|
|
38
|
+
if (f.denominator === 1) return num
|
|
39
|
+
|
|
40
|
+
return `\\frac{ ${num} }{ ${f.denominator} }`
|
|
24
41
|
}
|
|
25
42
|
|
|
26
|
-
set tex(value: string) {
|
|
43
|
+
set tex(value: string | null) {
|
|
27
44
|
this.#tex = value
|
|
28
45
|
}
|
|
29
46
|
|
|
30
|
-
get display(): string {
|
|
31
|
-
return this.#display
|
|
47
|
+
get display(): string | null {
|
|
48
|
+
if(this.#display) return this.#display
|
|
49
|
+
|
|
50
|
+
if (this.#root.isZero()) return this.#fraction.display
|
|
51
|
+
|
|
52
|
+
if (this.#fraction.isZero()) return this.#root.display
|
|
53
|
+
|
|
54
|
+
const [f] = Fraction.toSameDenominateur(this.#fraction, this.#root.factor)
|
|
55
|
+
|
|
56
|
+
const R = this.#root.clone().multiply(f.denominator).reduce()
|
|
57
|
+
const num = `${f.numerator}${R.withSign.display}`
|
|
58
|
+
|
|
59
|
+
if (f.denominator === 1) return num
|
|
60
|
+
|
|
61
|
+
return `(${num})/${f.denominator}`
|
|
32
62
|
}
|
|
33
63
|
|
|
34
|
-
set display(value: string) {
|
|
64
|
+
set display(value: string | null) {
|
|
35
65
|
this.#display = value
|
|
36
66
|
}
|
|
37
67
|
|
|
38
68
|
static fromFraction(value: InputValue<Fraction>): Solution {
|
|
39
69
|
const sol = new Solution()
|
|
40
|
-
sol.
|
|
70
|
+
sol.setExact()
|
|
41
71
|
|
|
42
72
|
const F = new Fraction(value)
|
|
43
73
|
sol.display = F.display
|
|
44
74
|
sol.tex = F.tex
|
|
45
75
|
|
|
76
|
+
sol.fraction = F
|
|
77
|
+
sol.root = new Root()
|
|
78
|
+
|
|
46
79
|
return sol
|
|
47
80
|
}
|
|
48
81
|
|
|
49
|
-
static fromQuadratic(
|
|
50
|
-
const [a, b, c] =
|
|
82
|
+
static fromQuadratic(A: InputValue<Fraction>, B: InputValue<Fraction>, C: InputValue<Fraction>): Solution[] {
|
|
83
|
+
const [a, b, c] = [A, B, C].map(x => new Fraction(x))
|
|
51
84
|
|
|
52
85
|
// D = b^2-4ac
|
|
53
86
|
const delta2 = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4))
|
|
@@ -65,10 +98,25 @@ export class Solution {
|
|
|
65
98
|
: [Solution.fromFraction(root1), Solution.fromFraction(root2)]
|
|
66
99
|
}
|
|
67
100
|
|
|
68
|
-
const
|
|
69
|
-
|
|
101
|
+
const sol1 = new Solution()
|
|
102
|
+
sol1.fraction = b.clone().opposite().divide(a).divide(2)
|
|
103
|
+
sol1.root = new Root().from(2, delta2, a.clone().multiply(2).inverse().opposite())
|
|
104
|
+
sol1.setExact(false)
|
|
105
|
+
|
|
106
|
+
const sol2 = new Solution()
|
|
107
|
+
sol2.fraction = b.clone().opposite().divide(a).divide(2)
|
|
108
|
+
sol2.root = new Root().from(2, delta2, a.clone().multiply(2).inverse())
|
|
109
|
+
sol2.setExact(false)
|
|
70
110
|
|
|
71
|
-
return
|
|
111
|
+
return [sol1, sol2]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get count(): number {
|
|
115
|
+
return this.#count
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
set count(value: number) {
|
|
119
|
+
this.#count = value
|
|
72
120
|
}
|
|
73
121
|
|
|
74
122
|
get exact(): boolean {
|
|
@@ -79,26 +127,41 @@ export class Solution {
|
|
|
79
127
|
this.#exact = value
|
|
80
128
|
}
|
|
81
129
|
|
|
82
|
-
|
|
83
|
-
this.#
|
|
84
|
-
return this
|
|
130
|
+
get fraction(): Fraction {
|
|
131
|
+
return this.#fraction
|
|
85
132
|
}
|
|
86
133
|
|
|
87
|
-
|
|
88
|
-
this.#
|
|
134
|
+
set fraction(value: Fraction) {
|
|
135
|
+
this.#fraction = value
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
isZero(): boolean {
|
|
139
|
+
return this.#fraction.isZero() && this.#root.isZero()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
reduce(): this {
|
|
143
|
+
// Reduce the root
|
|
144
|
+
this.#root.reduce()
|
|
145
|
+
this.#fraction.reduce()
|
|
146
|
+
|
|
89
147
|
return this
|
|
90
148
|
}
|
|
91
149
|
|
|
92
|
-
get
|
|
93
|
-
return this.#
|
|
150
|
+
get root(): Root {
|
|
151
|
+
return this.#root
|
|
94
152
|
}
|
|
95
153
|
|
|
96
|
-
set
|
|
97
|
-
this.#
|
|
154
|
+
set root(value: Root) {
|
|
155
|
+
this.#root = value
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
setExact(value = true): this {
|
|
159
|
+
this.#exact = value
|
|
160
|
+
return this
|
|
98
161
|
}
|
|
99
162
|
|
|
100
163
|
get value(): number {
|
|
101
|
-
|
|
164
|
+
return this.fraction.value + this.root.value
|
|
102
165
|
}
|
|
103
166
|
|
|
104
167
|
get variable(): string {
|