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.
Files changed (99) hide show
  1. package/dist/pimath.js +3106 -2873
  2. package/dist/pimath.js.map +1 -1
  3. package/package.json +13 -11
  4. package/src/algebra/equation.ts +113 -111
  5. package/src/algebra/equationSolver.ts +69 -120
  6. package/src/algebra/factor.ts +6 -7
  7. package/src/algebra/linearSystem.ts +97 -46
  8. package/src/algebra/logicalset.ts +51 -52
  9. package/src/algebra/monom.ts +23 -61
  10. package/src/algebra/operations.ts +0 -1
  11. package/src/algebra/polyFactor.ts +5 -5
  12. package/src/algebra/polynom.ts +69 -216
  13. package/src/analyze/index.ts +4 -0
  14. package/src/analyze/solution.ts +92 -29
  15. package/src/analyze/tableOfSigns.ts +1 -1
  16. package/src/coefficients/fraction.ts +189 -149
  17. package/src/coefficients/index.ts +1 -1
  18. package/src/coefficients/root.ts +66 -19
  19. package/src/geometry/TupleN.ts +128 -0
  20. package/src/geometry/circle.ts +308 -238
  21. package/src/geometry/geomMath.ts +4 -3
  22. package/src/geometry/index.ts +1 -0
  23. package/src/geometry/line.ts +221 -245
  24. package/src/geometry/line3.ts +78 -73
  25. package/src/geometry/plane3.ts +64 -55
  26. package/src/geometry/point.ts +57 -19
  27. package/src/geometry/triangle.ts +376 -248
  28. package/src/geometry/vector.ts +113 -229
  29. package/src/index.ts +13 -12
  30. package/src/numeric.ts +6 -9
  31. package/src/pimath.interface.ts +30 -28
  32. package/src/randomization/algebra/rndPolynom.ts +29 -15
  33. package/src/randomization/coefficient/rndFraction.ts +3 -3
  34. package/src/randomization/geometry/rndLine.ts +8 -10
  35. package/src/randomization/random.ts +11 -13
  36. package/src/randomization/rndTypes.ts +16 -12
  37. package/types/algebra/equation.d.ts +18 -17
  38. package/types/algebra/equation.d.ts.map +1 -1
  39. package/types/algebra/equationSolver.d.ts +5 -4
  40. package/types/algebra/equationSolver.d.ts.map +1 -1
  41. package/types/algebra/factor.d.ts +1 -1
  42. package/types/algebra/factor.d.ts.map +1 -1
  43. package/types/algebra/linearSystem.d.ts +23 -6
  44. package/types/algebra/linearSystem.d.ts.map +1 -1
  45. package/types/algebra/logicalset.d.ts +1 -1
  46. package/types/algebra/logicalset.d.ts.map +1 -1
  47. package/types/algebra/monom.d.ts +1 -6
  48. package/types/algebra/monom.d.ts.map +1 -1
  49. package/types/algebra/operations.d.ts.map +1 -1
  50. package/types/algebra/polyFactor.d.ts +4 -4
  51. package/types/algebra/polyFactor.d.ts.map +1 -1
  52. package/types/algebra/polynom.d.ts +10 -7
  53. package/types/algebra/polynom.d.ts.map +1 -1
  54. package/types/analyze/index.d.ts +2 -0
  55. package/types/analyze/index.d.ts.map +1 -0
  56. package/types/analyze/solution.d.ts +14 -8
  57. package/types/analyze/solution.d.ts.map +1 -1
  58. package/types/coefficients/fraction.d.ts +14 -12
  59. package/types/coefficients/fraction.d.ts.map +1 -1
  60. package/types/coefficients/index.d.ts +1 -1
  61. package/types/coefficients/index.d.ts.map +1 -1
  62. package/types/coefficients/root.d.ts +3 -0
  63. package/types/coefficients/root.d.ts.map +1 -1
  64. package/types/geometry/TupleAbstract.d.ts +22 -0
  65. package/types/geometry/TupleAbstract.d.ts.map +1 -0
  66. package/types/geometry/TupleN.d.ts +24 -0
  67. package/types/geometry/TupleN.d.ts.map +1 -0
  68. package/types/geometry/circle.d.ts +26 -17
  69. package/types/geometry/circle.d.ts.map +1 -1
  70. package/types/geometry/geomMath.d.ts +2 -1
  71. package/types/geometry/geomMath.d.ts.map +1 -1
  72. package/types/geometry/index.d.ts.map +1 -1
  73. package/types/geometry/line.d.ts +21 -30
  74. package/types/geometry/line.d.ts.map +1 -1
  75. package/types/geometry/line3.d.ts +19 -19
  76. package/types/geometry/line3.d.ts.map +1 -1
  77. package/types/geometry/matrix.d.ts +11 -11
  78. package/types/geometry/plane3.d.ts +10 -10
  79. package/types/geometry/plane3.d.ts.map +1 -1
  80. package/types/geometry/point.d.ts +11 -6
  81. package/types/geometry/point.d.ts.map +1 -1
  82. package/types/geometry/triangle.d.ts +68 -23
  83. package/types/geometry/triangle.d.ts.map +1 -1
  84. package/types/geometry/vector.d.ts +24 -44
  85. package/types/geometry/vector.d.ts.map +1 -1
  86. package/types/index.d.ts +5 -4
  87. package/types/index.d.ts.map +1 -1
  88. package/types/numeric.d.ts.map +1 -1
  89. package/types/pimath.interface.d.ts +18 -24
  90. package/types/pimath.interface.d.ts.map +1 -1
  91. package/types/randomization/algebra/rndPolynom.d.ts.map +1 -1
  92. package/types/randomization/coefficient/rndFraction.d.ts +1 -1
  93. package/types/randomization/coefficient/rndFraction.d.ts.map +1 -1
  94. package/types/randomization/geometry/rndLine.d.ts.map +1 -1
  95. package/types/randomization/random.d.ts +3 -2
  96. package/types/randomization/random.d.ts.map +1 -1
  97. package/types/randomization/rndTypes.d.ts +15 -10
  98. package/types/randomization/rndTypes.d.ts.map +1 -1
  99. package/src/coefficients/nthRoot.ts +0 -149
@@ -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: ISolution[]
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
- const tempPolynom: Polynom = new Polynom(M)
302
- factors = [tempPolynom.clone()]
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
- // Main loop
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
- // Check last item (degree zero)
356
- if (!pC.isDivisible(dC)) {
357
- return false
358
- }
316
+ if (solutions.length === 0) {
317
+ this.#factors = [this.clone()]
318
+ return this.#factors
319
+ }
359
320
 
360
- // Check the first item (degree max)
361
- return pX.isDivisible(dX)
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
- // Maybe there is still something in the Polynom (not everything was possible to factorize)
369
- if (!P.isOne()) {
370
- factors.push(P.clone())
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
- // Save the factors
375
- this.#factors = 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 = (): ISolution[] => {
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 instanceof Fraction) {
503
- return (this.evaluate(zero.exact) as Fraction).isZero()
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
- } else if (value instanceof Fraction) {
638
+ }
639
+
640
+ if (value instanceof Fraction) {
688
641
  return this.#multiplyByFraction(value)
689
- } else if (value instanceof Monom) {
642
+ }
643
+
644
+ if (value instanceof Monom) {
690
645
  return this.#multiplyByMonom(value)
691
- } else if (Number.isSafeInteger(value) && typeof value === 'number') {
646
+ }
647
+
648
+ if (Number.isSafeInteger(value) && typeof value === 'number') {
692
649
  return this.#multiplyByInteger(value)
693
- } else if (typeof value === 'string') {
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('Cannot multiply by this value.')
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(): ISolution[] {
809
+ get roots(): Solution[] {
854
810
  return this.#rootsCache ? this.#roots : this.getZeroes()
855
811
  }
856
812
 
857
- set roots(value: ISolution[]) {
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: ISolution[] = this.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(): ISolution[] {
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
  }
@@ -0,0 +1,4 @@
1
+ // Exports every files from the algebra folder
2
+
3
+ export * from "./solution"
4
+ export * from "./tableOfSigns"
@@ -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
- #display: string
6
+ #count: number
7
+ #display: string | null
8
8
  #exact: boolean
9
- #isZero: boolean
10
- #tex: string
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.isExact()
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(values: [InputValue<Fraction>, InputValue<Fraction>, InputValue<Fraction>]): Solution[] {
50
- const [a, b, c] = values.map(x => new Fraction(x))
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 solutions = [new Solution(), new Solution()]
69
- solutions.forEach(sol=> sol.isExact(false))
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 solutions
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
- isAZero(value = true): this {
83
- this.#isZero = value
84
- return this
130
+ get fraction(): Fraction {
131
+ return this.#fraction
85
132
  }
86
133
 
87
- isExact(value = true): this {
88
- this.#exact = value
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 isZero(): boolean {
93
- return this.#isZero
150
+ get root(): Root {
151
+ return this.#root
94
152
  }
95
153
 
96
- set isZero(value: boolean) {
97
- this.#isZero = value
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
- throw new Error("To be implemented")
164
+ return this.fraction.value + this.root.value
102
165
  }
103
166
 
104
167
  get variable(): string {
@@ -1,5 +1,5 @@
1
1
 
2
- // TODO: move the TableOfSigns system to a custom class.
2
+ // TODO: move the TableOfSigns asSystem to a custom class.
3
3
 
4
4
  import {Factor, PolyFactor, Polynom} from "../algebra"
5
5
  import type {InputAlgebra} from "../pimath.interface"