pimath 0.0.29 → 0.0.33

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 (86) hide show
  1. package/dev/pi.js +852 -488
  2. package/dev/pi.js.map +1 -1
  3. package/dist/pi.js +1 -1
  4. package/dist/pi.js.map +1 -1
  5. package/docs/assets/search.js +1 -1
  6. package/docs/classes/algebra.Equation.html +9 -9
  7. package/docs/classes/algebra.LinearSystem.html +1 -1
  8. package/docs/classes/algebra.Logicalset.html +2 -2
  9. package/docs/classes/algebra.Monom.html +42 -40
  10. package/docs/classes/algebra.Polynom.html +10 -10
  11. package/docs/classes/algebra.PolynomExpFactor.html +1 -0
  12. package/docs/classes/algebra.PolynomExpProduct.html +1 -0
  13. package/docs/classes/algebra.Rational.html +2 -2
  14. package/docs/classes/coefficients.Fraction.html +4 -4
  15. package/docs/classes/coefficients.Nthroot.html +1 -1
  16. package/docs/classes/geometry.Circle.html +2 -2
  17. package/docs/classes/geometry.Line.html +2 -2
  18. package/docs/classes/geometry.Point.html +1 -1
  19. package/docs/classes/geometry.Triangle.html +6 -6
  20. package/docs/classes/geometry.Vector.html +1 -1
  21. package/docs/classes/numeric.Numeric.html +5 -5
  22. package/docs/classes/shutingyard.Shutingyard.html +7 -8
  23. package/docs/enums/shutingyard.ShutingyardMode.html +1 -0
  24. package/docs/enums/shutingyard.ShutingyardType.html +1 -0
  25. package/docs/index.html +1 -1
  26. package/docs/interfaces/geometry.remarquableLines.html +1 -1
  27. package/docs/modules/algebra.html +1 -1
  28. package/docs/modules/coefficients.html +1 -1
  29. package/docs/modules/geometry.html +1 -1
  30. package/docs/modules/numeric.html +1 -1
  31. package/docs/modules/random.Random.html +1 -1
  32. package/docs/modules/random.html +1 -1
  33. package/docs/modules/shutingyard.html +1 -1
  34. package/docs/modules.html +1 -1
  35. package/esm/main.js +3 -1
  36. package/esm/main.js.map +1 -1
  37. package/esm/maths/algebra/equation.js +1 -1
  38. package/esm/maths/algebra/equation.js.map +1 -1
  39. package/esm/maths/algebra/index.d.ts +1 -0
  40. package/esm/maths/algebra/index.js +1 -0
  41. package/esm/maths/algebra/index.js.map +1 -1
  42. package/esm/maths/algebra/monom.d.ts +4 -1
  43. package/esm/maths/algebra/monom.js +54 -39
  44. package/esm/maths/algebra/monom.js.map +1 -1
  45. package/esm/maths/algebra/polynom.d.ts +19 -15
  46. package/esm/maths/algebra/polynom.js +242 -174
  47. package/esm/maths/algebra/polynom.js.map +1 -1
  48. package/esm/maths/coefficients/fraction.d.ts +3 -0
  49. package/esm/maths/coefficients/fraction.js +21 -8
  50. package/esm/maths/coefficients/fraction.js.map +1 -1
  51. package/esm/maths/{numexp.d.ts → expressions/numexp.d.ts} +3 -0
  52. package/esm/maths/{numexp.js → expressions/numexp.js} +43 -15
  53. package/esm/maths/expressions/numexp.js.map +1 -0
  54. package/esm/maths/expressions/polynomexp.bkp.d.ts +33 -0
  55. package/esm/maths/expressions/polynomexp.bkp.js +186 -0
  56. package/esm/maths/expressions/polynomexp.bkp.js.map +1 -0
  57. package/esm/maths/expressions/polynomexp.d.ts +52 -0
  58. package/esm/maths/expressions/polynomexp.js +233 -0
  59. package/esm/maths/expressions/polynomexp.js.map +1 -0
  60. package/esm/maths/geometry/line.d.ts +3 -2
  61. package/esm/maths/geometry/line.js +3 -2
  62. package/esm/maths/geometry/line.js.map +1 -1
  63. package/esm/maths/shutingyard.d.ts +6 -6
  64. package/esm/maths/shutingyard.js +1 -5
  65. package/esm/maths/shutingyard.js.map +1 -1
  66. package/package.json +1 -1
  67. package/{dev → public}/demo.css +0 -0
  68. package/{dev → public}/index.html +48 -13
  69. package/{dev → public}/playground.html +1 -1
  70. package/src/main.ts +13 -2
  71. package/src/maths/algebra/equation.ts +1 -1
  72. package/src/maths/algebra/index.ts +2 -1
  73. package/src/maths/algebra/monom.ts +77 -51
  74. package/src/maths/algebra/polynom.ts +445 -327
  75. package/src/maths/coefficients/fraction.ts +28 -11
  76. package/src/maths/{numexp.ts → expressions/numexp.ts} +40 -20
  77. package/src/maths/expressions/polynomexp.bkp.ts +223 -0
  78. package/src/maths/expressions/polynomexp.ts +309 -0
  79. package/src/maths/geometry/line.ts +4 -2
  80. package/src/maths/shutingyard.ts +11 -7
  81. package/tests/algebra/monom.test.ts +12 -8
  82. package/tests/algebra/polynom.test.ts +35 -2
  83. package/tests/numexp.test.ts +21 -1
  84. package/tests/polynomexp.test.ts +15 -0
  85. package/tests/shutingyard.test.ts +4 -4
  86. package/esm/maths/numexp.js.map +0 -1
@@ -3,11 +3,12 @@
3
3
  */
4
4
 
5
5
  import {literalType, Monom} from './monom';
6
- import {Shutingyard} from '../shutingyard';
6
+ import {Shutingyard, ShutingyardType, Token} from '../shutingyard';
7
7
  import {Numeric} from '../numeric';
8
- import {Random, randomPolynomConfig} from "../random";
9
8
  import {Fraction} from "../coefficients";
9
+ import {log} from "util";
10
10
 
11
+ export type PolynomParsingType = string|Polynom|number|Fraction|Monom
11
12
  /**
12
13
  * Polynom class can handle polynoms, reorder, resolve, ...
13
14
  * ```
@@ -16,16 +17,13 @@ import {Fraction} from "../coefficients";
16
17
  */
17
18
  export class Polynom {
18
19
  private _rawString: string;
19
- private _monoms: Monom[];
20
- private _factors: Polynom[];
21
- private _texString: string;
22
20
 
23
21
  /**
24
22
  *
25
23
  * @param {string} polynomString (optional) Default polynom to parse on class creation
26
24
  * @param values
27
25
  */
28
- constructor(polynomString?: string, ...values: unknown[]) {
26
+ constructor(polynomString?: PolynomParsingType, ...values: unknown[]) {
29
27
  this._monoms = [];
30
28
  this._factors = [];
31
29
  if (polynomString !== undefined) {
@@ -34,8 +32,8 @@ export class Polynom {
34
32
  return this;
35
33
  }
36
34
 
37
- // ------------------------------------------
38
- // Getter and setter
35
+ private _monoms: Monom[];
36
+
39
37
  // ------------------------------------------
40
38
  get monoms() {
41
39
  return this._monoms;
@@ -45,6 +43,11 @@ export class Polynom {
45
43
  this._monoms = M;
46
44
  }
47
45
 
46
+ // ------------------------------------------
47
+ // Getter and setter
48
+
49
+ private _factors: Polynom[];
50
+
48
51
  get factors(): Polynom[] {
49
52
  return this._factors;
50
53
  }
@@ -53,6 +56,12 @@ export class Polynom {
53
56
  this._factors = value;
54
57
  }
55
58
 
59
+ private _texString: string;
60
+
61
+ get texString(): string {
62
+ return this._texString;
63
+ }
64
+
56
65
  get texFactors(): string {
57
66
  this.factorize()
58
67
 
@@ -67,10 +76,6 @@ export class Polynom {
67
76
  return tex;
68
77
  }
69
78
 
70
- get texString(): string {
71
- return this._texString;
72
- }
73
-
74
79
  get length() {
75
80
  // TODO: Must reduce the monoms list to remove the zero coefficient.
76
81
  return this._monoms.length;
@@ -115,47 +120,36 @@ export class Polynom {
115
120
  return this.variables.length;
116
121
  }
117
122
 
118
- private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean): string => {
119
- let P: string = '';
120
-
121
- for (const k of this._monoms) {
122
- if (k.coefficient.value === 0) {
123
- continue;
124
- }
125
-
126
- P += `${(k.coefficient.sign() === 1 && (P !== '' || forceSign === true)) ? '+' : ''}${(output === 'tex') ? k.tex : k.display}`;
127
- }
128
-
129
- if (wrapParentheses === true && this.length > 1) {
130
- if (output === 'tex') {
131
- P = `\\left( ${P} \\right)`;
132
- } else {
133
- P = `(${P})`;
134
- }
135
- }
136
-
137
- if (P === '') {
138
- P = '0';
139
- }
140
- return P;
141
- };
142
-
143
-
144
- // ------------------------------------------
145
- // Creation / parsing functions
146
123
  // ------------------------------------------
147
124
  /**
148
125
  * Parse a string to a polynom.
149
126
  * @param inputStr
150
127
  * @param values: as string, numbers or fractions
151
128
  */
152
- parse = (inputStr: string, ...values: unknown[]): Polynom => {
129
+ parse = (inputStr: PolynomParsingType, ...values: unknown[]): Polynom => {
130
+ // Reset the main variables.
131
+ this._monoms = []
132
+ this._factors = []
133
+
134
+ if(typeof inputStr === 'string') {
135
+ return this._parseString(inputStr, ...values)
136
+ }else if(typeof inputStr === 'number' || inputStr instanceof Fraction || inputStr instanceof Monom){
137
+ this._monoms.push(new Monom(inputStr))
138
+ }else if(inputStr instanceof Polynom){
139
+ for(const m of inputStr.monoms){
140
+ this._monoms.push(m.clone())
141
+ }
142
+ }
153
143
 
144
+ return this
145
+ };
146
+
147
+ private _parseString(inputStr: string, ...values:unknown[]): Polynom{
154
148
  if (values === undefined || values.length === 0) {
155
149
  inputStr = '' + inputStr;
156
150
  this._rawString = inputStr;
157
151
 
158
- // Parse the polynom using the shuting yard algorithm
152
+ // Parse the polynom using the shutting yard algorithm
159
153
  if (inputStr !== '' && !isNaN(Number(inputStr))) {
160
154
  this.empty();
161
155
  // It's a simple number.
@@ -201,52 +195,11 @@ export class Polynom {
201
195
  } else {
202
196
  return this.zero();
203
197
  }
198
+ }
204
199
 
205
- };
206
-
207
- /**
208
- * Main parse using a shutting yard class
209
- * @param inputStr
210
- */
211
- private shutingYardToReducedPolynom = (inputStr: string): Polynom => {
212
- // Get the RPN array of the current expression
213
- const SY: Shutingyard = new Shutingyard().parse(inputStr);
214
- const rpn: { token: string, tokenType: string }[] = SY.rpn;
215
- let m1: Polynom;
216
- let m2: Polynom;
217
-
218
- let stack: Polynom[] = [],
219
- previousToken: string = null,
220
- tempPolynom
221
-
222
- for (const element of rpn) {
223
- if (element.tokenType === 'coefficient' || element.tokenType === 'variable') {
224
- tempPolynom = new Polynom().zero();
225
- tempPolynom.monoms = [new Monom(element.token)]
226
- stack.push(tempPolynom.clone())
227
- } else if (element.tokenType === 'operation') {
228
- m2 = (stack.pop()) || new Polynom().zero();
229
- m1 = (stack.pop()) || new Polynom().zero();
230
- switch (element.token) {
231
- case '+':
232
- stack.push(m1.add(m2))
233
- break;
234
- case '-':
235
- stack.push(m1.subtract(m2))
236
- break;
237
- case '*':
238
- stack.push(m1.multiply(m2))
239
- break;
240
- case '^':
241
- stack.push(m1.pow(+previousToken))
242
- }
243
- }
244
- previousToken = element.token;
245
- }
246
200
 
247
- this._monoms = stack[0].monoms;
248
- return this;
249
- }
201
+ // ------------------------------------------
202
+ // Creation / parsing functions
250
203
 
251
204
  /**
252
205
  * Clone the polynom
@@ -287,6 +240,29 @@ export class Polynom {
287
240
  return this;
288
241
  };
289
242
 
243
+ // ------------------------------------------
244
+ opposed = (): Polynom => {
245
+ this._monoms = this._monoms.map(m => m.opposed());
246
+ return this;
247
+ };
248
+
249
+ add = (...values: unknown[]): Polynom => {
250
+
251
+ for (let value of values) {
252
+ if (value instanceof Polynom) {
253
+ this._monoms = this._monoms.concat(value.monoms);
254
+ } else if (value instanceof Monom) {
255
+ this._monoms.push(value.clone());
256
+ } else if (Number.isSafeInteger(value)) {
257
+ this._monoms.push(new Monom(value.toString()));
258
+ } else {
259
+ this._monoms.push(new Monom(value));
260
+ }
261
+ }
262
+
263
+ return this.reduce();
264
+ };
265
+
290
266
  // // -----------------------------------------------
291
267
  // // Polynom generators and randomizers
292
268
  // // -----------------------------------------------
@@ -351,28 +327,6 @@ export class Polynom {
351
327
 
352
328
  // ------------------------------------------
353
329
  // Mathematical operations
354
- // ------------------------------------------
355
- opposed = (): Polynom => {
356
- this._monoms = this._monoms.map(m => m.opposed());
357
- return this;
358
- };
359
-
360
- add = (...values: unknown[]): Polynom => {
361
-
362
- for (let value of values) {
363
- if (value instanceof Polynom) {
364
- this._monoms = this._monoms.concat(value.monoms);
365
- } else if (value instanceof Monom) {
366
- this._monoms.push(value.clone());
367
- } else if (Number.isSafeInteger(value)) {
368
- this._monoms.push(new Monom(value.toString()));
369
- } else {
370
- this._monoms.push(new Monom(value));
371
- }
372
- }
373
-
374
- return this.reduce();
375
- };
376
330
 
377
331
  subtract = (...values: unknown[]): Polynom => {
378
332
 
@@ -398,7 +352,7 @@ export class Polynom {
398
352
  return this.multiplyByFraction(value);
399
353
  } else if (value instanceof Monom) {
400
354
  return this.multiplyByMonom(value);
401
- } else if (Number.isSafeInteger(value) && typeof value==='number') {
355
+ } else if (Number.isSafeInteger(value) && typeof value === 'number') {
402
356
  return this.multiplyByInteger(value);
403
357
  }
404
358
 
@@ -406,37 +360,6 @@ export class Polynom {
406
360
  return this;
407
361
  }
408
362
 
409
- private multiplyByPolynom = (P: Polynom): Polynom => {
410
- const M: Monom[] = [];
411
- for (const m1 of this._monoms) {
412
- for (const m2 of P.monoms) {
413
- M.push(Monom.xmultiply(m1, m2));
414
- }
415
- }
416
-
417
- this._monoms = M;
418
- return this.reduce();
419
- };
420
-
421
- private multiplyByFraction = (F: Fraction): Polynom => {
422
- for (const m of this._monoms) {
423
- m.coefficient.multiply(F);
424
- }
425
-
426
- return this.reduce();
427
- };
428
-
429
- private multiplyByInteger = (nb: number): Polynom => {
430
- return this.multiplyByFraction(new Fraction(nb));
431
- };
432
-
433
- private multiplyByMonom = (M: Monom): Polynom => {
434
- for (const m of this._monoms) {
435
- m.multiply(M)
436
- }
437
- return this.reduce();
438
- };
439
-
440
363
  /**
441
364
  * Divide the current polynom by another polynom.
442
365
  * @param P
@@ -476,31 +399,19 @@ export class Polynom {
476
399
  reminder.subtract(P.clone().multiply(newM));
477
400
  }
478
401
 
402
+ quotient.reduce()
403
+ reminder.reduce()
479
404
  return {quotient, reminder};
480
405
  };
481
406
 
482
407
  divide = (value: unknown): Polynom => {
483
408
  if (value instanceof Fraction) {
484
- this.divideByFraction(value);
485
- } else if (typeof value==='number' && Number.isSafeInteger(value)) {
409
+ return this.divideByFraction(value);
410
+ } else if (typeof value === 'number' && Number.isSafeInteger(value)) {
486
411
  return this.divideByInteger(value);
487
412
  }
488
- }
489
-
490
- private divideByInteger = (nb: number): Polynom => {
491
- const nbF = new Fraction(nb);
492
- for (const m of this._monoms) {
493
- m.coefficient.divide(nbF);
494
- }
495
- return this;
496
- };
497
413
 
498
- private divideByFraction = (F: Fraction): Polynom => {
499
- for (const m of this._monoms) {
500
- m.coefficient.divide(F);
501
- }
502
- return this;
503
- };
414
+ }
504
415
 
505
416
  pow = (nb: number): Polynom => {
506
417
  if (!Number.isSafeInteger(nb)) {
@@ -520,9 +431,6 @@ export class Polynom {
520
431
  return this.reduce();
521
432
  };
522
433
 
523
-
524
- // ------------------------------------------
525
- // Compare functions
526
434
  // ------------------------------------------
527
435
  /**
528
436
  * Compare the current coefficient with another coefficient
@@ -686,8 +594,11 @@ export class Polynom {
686
594
  // TODO: Maybe it's enough to just make this test !
687
595
  return polynomStringNormalized === P.reduce().reorder().display
688
596
  }
597
+
598
+
689
599
  // ------------------------------------------
690
- // Misc polynoms functions
600
+ // Compare functions
601
+
691
602
  // -------------------------------------
692
603
  reduce = (): Polynom => {
693
604
  for (let i = 0; i < this._monoms.length; i++) {
@@ -777,6 +688,7 @@ export class Polynom {
777
688
  //console.log('Evaluate polynom: ', monom.display, values, monom.evaluate(values).display);
778
689
  r.add(monom.evaluate(values));
779
690
  });
691
+
780
692
  return r;
781
693
  };
782
694
 
@@ -798,6 +710,8 @@ export class Polynom {
798
710
  }
799
711
  return dP
800
712
  }
713
+ // ------------------------------------------
714
+ // Misc polynoms functions
801
715
 
802
716
  integrate = (a: Fraction | number, b: Fraction | number, letter?: string): Fraction => {
803
717
  const primitive = this.primitive(letter)
@@ -813,8 +727,7 @@ export class Polynom {
813
727
 
814
728
  return primitive.evaluate(valuesB).subtract(primitive.evaluate(valuesA))
815
729
  }
816
- // ------------------------------------------
817
- // Polynoms factorization functions
730
+
818
731
  // -------------------------------------
819
732
  /**
820
733
  * Factorize a polynom and store the best results in factors.
@@ -827,6 +740,7 @@ export class Polynom {
827
740
  let P = this.clone().reorder(),
828
741
  M = P.commonMonom(),
829
742
  tempPolynom: Polynom
743
+
830
744
  // It has a common monom.
831
745
  if (!M.isOne()) {
832
746
  tempPolynom = new Polynom()
@@ -837,10 +751,10 @@ export class Polynom {
837
751
 
838
752
  let securityLoop = P.degree().clone().multiply(2).value
839
753
  // securityLoop = 0
754
+
840
755
  while (securityLoop >= 0) {
841
756
  securityLoop--
842
757
 
843
-
844
758
  if (P.monoms.length < 2) {
845
759
  if (!P.isOne()) {
846
760
  factors.push(P.clone());
@@ -851,9 +765,6 @@ export class Polynom {
851
765
  let m1 = P.monoms[0].dividers,
852
766
  m2 = P.monoms[P.monoms.length - 1].dividers
853
767
 
854
- // console.log('CURRENT VALUE')
855
- // console.log(P.tex)
856
- // console.log('---------------------')
857
768
  for (let m1d of m1) {
858
769
  for (let m2d of m2) {
859
770
  // if(m1d.degree()===m2d.degree()){continue}
@@ -862,7 +773,6 @@ export class Polynom {
862
773
  dividerPolynom.monoms = [m1d.clone(), m2d.clone()]
863
774
  result = P.euclidian(dividerPolynom)
864
775
 
865
- // console.log(dividerPolynom.tex, '=>', result.reminder.tex, '|||||', result.quotient.tex)
866
776
  if (result.reminder.isZero()) {
867
777
  P = result.quotient.clone();
868
778
  factors.push(dividerPolynom)
@@ -875,172 +785,40 @@ export class Polynom {
875
785
  P = result.quotient.clone();
876
786
  factors.push(dividerPolynom)
877
787
  }
878
- // console.log(dividerPolynom.tex, '=>', result.reminder.tex)
879
788
  }
880
789
  }
881
790
  }
882
-
883
791
  }
884
792
 
885
793
  this.factors = factors
886
794
  return factors;
887
795
  }
888
796
 
889
- private _factorize2ndDegree = (letter: string): Polynom[] => {
890
- let P1: Polynom, P2: Polynom,
891
- a, b, c, delta, x1, x2, factor;
892
-
893
- // One variable only
894
- if (this.numberOfVars === 1) {
895
- a = this.monomByDegree(2, letter).coefficient;
896
- b = this.monomByDegree(1, letter).coefficient;
897
- c = this.monomByDegree(0, letter).coefficient;
898
- delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4));
899
-
900
- if (delta.isZero()) {
901
- x1 = b.clone().opposed().divide(a.clone().multiply(2))
902
- P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
903
- P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
904
- factor = a.divide(x1.denominator).divide(x1.denominator);
797
+ // TODO: get zeroes for more than first degree and for more than natural degrees
798
+ getZeroes = (): (Fraction | boolean)[] => {
799
+ const Z: Fraction[] = [];
905
800
 
906
- if (!factor.isOne()) {
907
- // TODO: Update new Polynom to accept anything...
908
- return [new Polynom(factor.display), P1, P2]
801
+ switch (this.degree().value) {
802
+ case 0:
803
+ if (this._monoms[0].coefficient.value === 0) {
804
+ return [true];
909
805
  } else {
910
- return [P1, P2]
911
- }
912
- } else if (delta.isPositive() && delta.isSquare()) {
913
- x1 = b.clone().opposed()
914
- .add(delta.clone().sqrt())
915
- .divide(a.clone().multiply(2))
916
- x2 = b.clone().opposed()
917
- .subtract(delta.clone().sqrt())
918
- .divide(a.clone().multiply(2))
919
-
920
- // (2x+5)(3x-2)
921
- // 6x^2+11x-10
922
- // a = 6, b = 11, c = -10
923
- // delta = 121-4*6*(-10) = 361= 19^2
924
- // x1 = (-11 + 19) / 12 = 8/12 = 2/3
925
- // x2 = (-11 - 19) / 12 = -30/12 = -5/2
926
- factor = a.divide(x1.denominator).divide(x2.denominator);
927
- if (factor.isOne()) {
928
- return [
929
- new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
930
- new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
931
- ]
932
- } else {
933
- return [
934
- new Polynom(factor.display),
935
- new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
936
- new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
937
- ]
938
-
939
- }
940
- } else {
941
- // No solution possible - return the complete value.
942
- return [this.clone()]
943
- }
944
- } else {
945
- // If multiple variables, only handle perfect squares...
946
- a = this.monomByDegree(2, letter);
947
- b = this.monomByDegree(1, letter);
948
- c = this.monomByDegree(0, letter);
949
-
950
-
951
- if (a.isLiteralSquare() && c.isLiteralSquare()) {
952
- // Check the middle item is same as...
953
- if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
954
- // Determine if the coefficient values matches.
955
-
956
- // Search 4 values (r, s, t, u) that matches:
957
- // (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
958
-
959
- let xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient);
960
- let xFactors = xPolynom._factorize2ndDegree('x');
961
-
962
- let factors = [], xyzPolynom: Polynom;
963
-
964
- if (xFactors.length >= 2) {
965
- for (let p of xFactors) {
966
- if (p.degree().isZero()) {
967
- factors.push(p.clone())
968
- } else {
969
- xyzPolynom = p.clone();
970
- xyzPolynom.monoms[0].literal = a.literalSqrt
971
- xyzPolynom.monoms[1].literal = c.literalSqrt
972
- factors.push(xyzPolynom.clone())
973
- }
974
- }
975
- return factors
976
- }
977
- }
978
- }
979
-
980
- return [this.clone()]
981
- //
982
- // console.log(a.tex, b.tex, c.tex)
983
- // if (a.isSquare() && c.isSquare()) {
984
- // console.log('A C squares')
985
- // if (a.clone().sqrt().multiply(c.clone().sqrt()).multiplyByNumber(2).isSameAs(b)) {
986
- // console.log('HERE')
987
- // if (a.coefficient.sign() === b.coefficient.sign()) {
988
- // return []
989
- // }else{
990
- // return []
991
- // }
992
- // }
993
- // } else if(a.isLiteralSquare() && c.isLiteralSquare()) {
994
- // console.log('A C litteral SQUARES')
995
- // // Check that the middle element is the product of a and c.
996
- //
997
- // if(b.clone().pow(2).isSameAs(a.clone().multiply(c))){
998
- // console.log('SAME')
999
- //
1000
- // }else{
1001
- // console.log('NOT SAME')
1002
- // }
1003
- //
1004
- // return [this.clone()]
1005
- // } else {
1006
- // console.log('NOT SQUARES AT ALL !!!!')
1007
- // }
1008
-
1009
- }
1010
- }
1011
-
1012
- private _factorizeByGroups = (): Polynom[] => {
1013
- // TODO: Factorize by groups.
1014
- return [];
1015
- }
1016
- // ------------------------------------------
1017
- // Polynoms helpers functions
1018
- // -------------------------------------
1019
- // TODO: get zeroes for more than first degree and for more than natural degrees
1020
- getZeroes = (): (Fraction | boolean)[] => {
1021
- const Z: Fraction[] = [];
1022
-
1023
- switch (this.degree().value) {
1024
- case 0:
1025
- if (this._monoms[0].coefficient.value === 0) {
1026
- return [true];
1027
- } else {
1028
- return [false];
1029
- }
1030
- case 1:
1031
- // There is only one monoms,
1032
- if (this._monoms.length === 1) {
1033
- return [new Fraction().zero()];
1034
- } else {
1035
- const P = this.clone().reduce().reorder();
1036
- return [P.monoms[1].coefficient.opposed().divide(P.monoms[0].coefficient)];
1037
- }
1038
- // TODO: Determine the zeros of an equation of second degree.
1039
- //case 2:
1040
- default:
1041
- // Make sure the polynom is factorized.
1042
- if (this._factors.length === 0) {
1043
- this.factorize()
806
+ return [false];
807
+ }
808
+ case 1:
809
+ // There is only one monoms,
810
+ if (this._monoms.length === 1) {
811
+ return [new Fraction().zero()];
812
+ } else {
813
+ const P = this.clone().reduce().reorder();
814
+ return [P.monoms[1].coefficient.opposed().divide(P.monoms[0].coefficient)];
815
+ }
816
+ // TODO: Determine the zeros of an equation of second degree.
817
+ //case 2:
818
+ default:
819
+ // Make sure the polynom is factorized.
820
+ if (this._factors.length === 0) {
821
+ this.factorize()
1044
822
  }
1045
823
 
1046
824
  let zeroes = [], zeroesAsTex = [];
@@ -1085,9 +863,8 @@ export class Polynom {
1085
863
  return Z;
1086
864
  };
1087
865
 
1088
-
1089
866
  // TODO: analyse the next functions to determine if they are useful or not...
1090
- monomByDegree = (degree?: Fraction|number, letter?: string): Monom => {
867
+ monomByDegree = (degree?: Fraction | number, letter?: string): Monom => {
1091
868
  if (degree === undefined) {
1092
869
  // return the highest degree monom.
1093
870
  return this.monomByDegree(this.degree(letter), letter);
@@ -1105,7 +882,7 @@ export class Polynom {
1105
882
  return new Monom().zero();
1106
883
  };
1107
884
 
1108
- monomsByDegree = (degree?: number|Fraction, letter?: string): Monom[] => {
885
+ monomsByDegree = (degree?: number | Fraction, letter?: string): Monom[] => {
1109
886
  if (degree === undefined) {
1110
887
  // return the highest degree monom.
1111
888
  return this.monomsByDegree(this.degree(letter));
@@ -1137,7 +914,6 @@ export class Polynom {
1137
914
  return new Monom().zero();
1138
915
  };
1139
916
 
1140
-
1141
917
  // Next functions are used for for commonMonom, which is used in the factorize method.
1142
918
  getDenominators = (): number[] => {
1143
919
  const denominators: number[] = [];
@@ -1158,6 +934,8 @@ export class Polynom {
1158
934
  lcmDenominator = (): number => {
1159
935
  return Numeric.lcm(...this.getDenominators());
1160
936
  };
937
+ // ------------------------------------------
938
+ // Polynoms factorization functions
1161
939
 
1162
940
  gcdDenominator = (): number => {
1163
941
  return Numeric.gcd(...this.getDenominators());
@@ -1170,6 +948,9 @@ export class Polynom {
1170
948
  gcdNumerator = (): number => {
1171
949
  return Numeric.gcd(...this.getNumerators());
1172
950
  };
951
+ // ------------------------------------------
952
+ // Polynoms helpers functions
953
+ // -------------------------------------
1173
954
 
1174
955
  commonMonom = (): Monom => {
1175
956
  let M = new Monom().one(), numerator: number, denominator: number, degree = this.degree();
@@ -1190,4 +971,341 @@ export class Polynom {
1190
971
  }
1191
972
  return M;
1192
973
  }
974
+
975
+ private genDisplay = (output?: string, forceSign?: boolean, wrapParentheses?: boolean): string => {
976
+ let P: string = '';
977
+
978
+ for (const k of this._monoms) {
979
+ if (k.coefficient.value === 0) {
980
+ continue;
981
+ }
982
+
983
+ P += `${(k.coefficient.sign() === 1 && (P !== '' || forceSign === true)) ? '+' : ''}${(output === 'tex') ? k.tex : k.display}`;
984
+ }
985
+
986
+ if (wrapParentheses === true && this.length > 1) {
987
+ if (output === 'tex') {
988
+ P = `\\left( ${P} \\right)`;
989
+ } else {
990
+ P = `(${P})`;
991
+ }
992
+ }
993
+
994
+ if (P === '') {
995
+ P = '0';
996
+ }
997
+ return P;
998
+ };
999
+
1000
+
1001
+ static addToken = (stack: Polynom[], element: Token): void => {
1002
+
1003
+ switch(element.tokenType){
1004
+ case ShutingyardType.COEFFICIENT:
1005
+ stack.push(new Polynom( element.token ))
1006
+ break
1007
+
1008
+ case ShutingyardType.VARIABLE:
1009
+ stack.push(new Polynom().add(new Monom(element.token)))
1010
+ break
1011
+
1012
+ case ShutingyardType.CONSTANT:
1013
+ // TODO: add constant support to Polynom parsing.
1014
+ console.log('Actually, not supported - will be added later !')
1015
+ break
1016
+
1017
+ case ShutingyardType.OPERATION:
1018
+ if(stack.length>=2){
1019
+ const b = stack.pop(),
1020
+ a = stack.pop()
1021
+
1022
+ if(element.token === '+'){
1023
+ stack.push(a.add(b))
1024
+ }else if(element.token === '-'){
1025
+ stack.push(a.subtract(b))
1026
+ }else if(element.token === '*'){
1027
+ stack.push(a.multiply(b))
1028
+ }else if(element.token === '/'){
1029
+ if(b.degree().isStrictlyPositive()){
1030
+ console.log('divide by a polynom -> should create a rational polynom !')
1031
+ }else {
1032
+ stack.push(a.divide(b.monoms[0].coefficient))
1033
+
1034
+ }
1035
+ }else if(element.token === '^'){
1036
+ if(b.degree().isStrictlyPositive()) {
1037
+ console.error('Cannot elevate a polynom with another polynom !')
1038
+ }else {
1039
+ if(b.monoms[0].coefficient.isRelative()) {
1040
+ // Integer power
1041
+ stack.push(a.pow(b.monoms[0].coefficient.value))
1042
+ }else{
1043
+ // Only allow power if the previous polynom is only a monom, without coefficient.
1044
+ if(a.monoms.length===1 && a.monoms[0].coefficient.isOne()){
1045
+ for (let letter in a.monoms[0].literal) {
1046
+ a.monoms[0].literal[letter].multiply(b.monoms[0].coefficient)
1047
+ }
1048
+ stack.push(a)
1049
+ }else {
1050
+ console.error('Cannot have power with fraction')
1051
+ }
1052
+ }
1053
+ }
1054
+ }
1055
+ }else{
1056
+ console.log('Stack size: ', stack.length)
1057
+ if(element.token === '-'){
1058
+ stack.push(stack.pop().opposed())
1059
+ }else{
1060
+ console.log('While parsing, cannot apply ', element.token, 'to', stack[0].tex)
1061
+ }
1062
+ }
1063
+ break
1064
+
1065
+ case ShutingyardType.MONOM:
1066
+ // Should never appear.
1067
+ console.error('The monom token should not appear here')
1068
+ break;
1069
+
1070
+ case ShutingyardType.FUNCTION:
1071
+ // Should never appear.
1072
+ console.log('The function token should not appear here - might be introduced later.')
1073
+ break;
1074
+ }
1075
+ }
1076
+ /**
1077
+ * Main parse using a shutting yard class
1078
+ * @param inputStr
1079
+ */
1080
+ private shutingYardToReducedPolynom = (inputStr: string): Polynom => {
1081
+ // Get the RPN array of the current expression
1082
+ const SY: Shutingyard = new Shutingyard().parse(inputStr);
1083
+ const rpn: { token: string, tokenType: string }[] = SY.rpn;
1084
+
1085
+ // New version for reducing shuting yard.
1086
+ this.zero()
1087
+
1088
+ let stack: Polynom[] = [],
1089
+ monom: Monom = new Monom()
1090
+
1091
+ // Loop through the
1092
+ for (const element of rpn) {
1093
+ Polynom.addToken(stack, element);
1094
+ }
1095
+
1096
+ if (stack.length === 1) {
1097
+ this.add(stack[0])
1098
+ }
1099
+
1100
+ return this
1101
+ /**
1102
+ let m1: Polynom;
1103
+ let m2: Polynom;
1104
+
1105
+ let stack: Polynom[] = [],
1106
+ previousToken: string = null,
1107
+ tempPolynom
1108
+
1109
+ for (const element of rpn) {
1110
+ if (element.tokenType === 'coefficient' || element.tokenType === 'variable') {
1111
+ tempPolynom = new Polynom().zero();
1112
+ tempPolynom.monoms = [new Monom(element.token)]
1113
+ stack.push(tempPolynom.clone())
1114
+ } else if (element.tokenType === 'operation') {
1115
+ m2 = (stack.pop()) || new Polynom().zero();
1116
+ m1 = (stack.pop()) || new Polynom().zero();
1117
+ switch (element.token) {
1118
+ case '+':
1119
+ stack.push(m1.add(m2))
1120
+ break;
1121
+ case '-':
1122
+ stack.push(m1.subtract(m2))
1123
+ break;
1124
+ case '*':
1125
+ stack.push(m1.multiply(m2))
1126
+ break;
1127
+ case '^':
1128
+ stack.push(m1.pow(+previousToken))
1129
+ }
1130
+ }
1131
+ previousToken = element.token;
1132
+ }
1133
+
1134
+ this._monoms = stack[0].monoms;
1135
+ return this;*/
1136
+ }
1137
+
1138
+ private multiplyByPolynom = (P: Polynom): Polynom => {
1139
+ const M: Monom[] = [];
1140
+ for (const m1 of this._monoms) {
1141
+ for (const m2 of P.monoms) {
1142
+ M.push(Monom.xmultiply(m1, m2));
1143
+ }
1144
+ }
1145
+
1146
+ this._monoms = M;
1147
+ return this.reduce();
1148
+ };
1149
+
1150
+ private multiplyByFraction = (F: Fraction): Polynom => {
1151
+ for (const m of this._monoms) {
1152
+ m.coefficient.multiply(F);
1153
+ }
1154
+
1155
+ return this.reduce();
1156
+ };
1157
+
1158
+ private multiplyByInteger = (nb: number): Polynom => {
1159
+ return this.multiplyByFraction(new Fraction(nb));
1160
+ };
1161
+
1162
+ private multiplyByMonom = (M: Monom): Polynom => {
1163
+ for (const m of this._monoms) {
1164
+ m.multiply(M)
1165
+ }
1166
+ return this.reduce();
1167
+ };
1168
+
1169
+ private divideByInteger = (nb: number): Polynom => {
1170
+ const nbF = new Fraction(nb);
1171
+ for (const m of this._monoms) {
1172
+ m.coefficient.divide(nbF);
1173
+ }
1174
+ return this;
1175
+ };
1176
+
1177
+ private divideByFraction = (F: Fraction): Polynom => {
1178
+ for (const m of this._monoms) {
1179
+ m.coefficient.divide(F);
1180
+ }
1181
+ return this;
1182
+ };
1183
+
1184
+ private _factorize2ndDegree = (letter: string): Polynom[] => {
1185
+ let P1: Polynom, P2: Polynom,
1186
+ a, b, c, delta, x1, x2, factor;
1187
+
1188
+ // One variable only
1189
+ if (this.numberOfVars === 1) {
1190
+ a = this.monomByDegree(2, letter).coefficient;
1191
+ b = this.monomByDegree(1, letter).coefficient;
1192
+ c = this.monomByDegree(0, letter).coefficient;
1193
+ delta = b.clone().pow(2).subtract(a.clone().multiply(c).multiply(4));
1194
+
1195
+ if (delta.isZero()) {
1196
+ x1 = b.clone().opposed().divide(a.clone().multiply(2))
1197
+ P1 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
1198
+ P2 = new Polynom(letter).subtract(x1.display).multiply(x1.denominator)
1199
+ factor = a.divide(x1.denominator).divide(x1.denominator);
1200
+
1201
+ if (!factor.isOne()) {
1202
+ // TODO: Update new Polynom to accept anything...
1203
+ return [new Polynom(factor.display), P1, P2]
1204
+ } else {
1205
+ return [P1, P2]
1206
+ }
1207
+ } else if (delta.isPositive() && delta.isSquare()) {
1208
+ x1 = b.clone().opposed()
1209
+ .add(delta.clone().sqrt())
1210
+ .divide(a.clone().multiply(2))
1211
+ x2 = b.clone().opposed()
1212
+ .subtract(delta.clone().sqrt())
1213
+ .divide(a.clone().multiply(2))
1214
+
1215
+ // (2x+5)(3x-2)
1216
+ // 6x^2+11x-10
1217
+ // a = 6, b = 11, c = -10
1218
+ // delta = 121-4*6*(-10) = 361= 19^2
1219
+ // x1 = (-11 + 19) / 12 = 8/12 = 2/3
1220
+ // x2 = (-11 - 19) / 12 = -30/12 = -5/2
1221
+ factor = a.divide(x1.denominator).divide(x2.denominator);
1222
+ if (factor.isOne()) {
1223
+ return [
1224
+ new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
1225
+ new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
1226
+ ]
1227
+ } else {
1228
+ return [
1229
+ new Polynom(factor.display),
1230
+ new Polynom(letter).subtract(x1.display).multiply(x1.denominator),
1231
+ new Polynom(letter).subtract(x2.display).multiply(x2.denominator),
1232
+ ]
1233
+
1234
+ }
1235
+ } else {
1236
+ // No solution possible - return the complete value.
1237
+ return [this.clone()]
1238
+ }
1239
+ } else {
1240
+ // If multiple variables, only handle perfect squares...
1241
+ a = this.monomByDegree(2, letter);
1242
+ b = this.monomByDegree(1, letter);
1243
+ c = this.monomByDegree(0, letter);
1244
+
1245
+
1246
+ if (a.isLiteralSquare() && c.isLiteralSquare()) {
1247
+ // Check the middle item is same as...
1248
+ if (b.clone().pow(2).isSameAs(a.clone().multiply(c))) {
1249
+ // Determine if the coefficient values matches.
1250
+
1251
+ // Search 4 values (r, s, t, u) that matches:
1252
+ // (r X + s Y)(t X + u Y) = rt X^2 + (ru + st) XY + su Y^2
1253
+
1254
+ let xPolynom = new Polynom('x', a.coefficient, b.coefficient, c.coefficient);
1255
+ let xFactors = xPolynom._factorize2ndDegree('x');
1256
+
1257
+ let factors = [], xyzPolynom: Polynom;
1258
+
1259
+ if (xFactors.length >= 2) {
1260
+ for (let p of xFactors) {
1261
+ if (p.degree().isZero()) {
1262
+ factors.push(p.clone())
1263
+ } else {
1264
+ xyzPolynom = p.clone();
1265
+ xyzPolynom.monoms[0].literal = a.literalSqrt
1266
+ xyzPolynom.monoms[1].literal = c.literalSqrt
1267
+ factors.push(xyzPolynom.clone())
1268
+ }
1269
+ }
1270
+ return factors
1271
+ }
1272
+ }
1273
+ }
1274
+
1275
+ return [this.clone()]
1276
+ //
1277
+ // console.log(a.tex, b.tex, c.tex)
1278
+ // if (a.isSquare() && c.isSquare()) {
1279
+ // console.log('A C squares')
1280
+ // if (a.clone().sqrt().multiply(c.clone().sqrt()).multiplyByNumber(2).isSameAs(b)) {
1281
+ // console.log('HERE')
1282
+ // if (a.coefficient.sign() === b.coefficient.sign()) {
1283
+ // return []
1284
+ // }else{
1285
+ // return []
1286
+ // }
1287
+ // }
1288
+ // } else if(a.isLiteralSquare() && c.isLiteralSquare()) {
1289
+ // console.log('A C litteral SQUARES')
1290
+ // // Check that the middle element is the product of a and c.
1291
+ //
1292
+ // if(b.clone().pow(2).isSameAs(a.clone().multiply(c))){
1293
+ // console.log('SAME')
1294
+ //
1295
+ // }else{
1296
+ // console.log('NOT SAME')
1297
+ // }
1298
+ //
1299
+ // return [this.clone()]
1300
+ // } else {
1301
+ // console.log('NOT SQUARES AT ALL !!!!')
1302
+ // }
1303
+
1304
+ }
1305
+ }
1306
+
1307
+ private _factorizeByGroups = (): Polynom[] => {
1308
+ // TODO: Factorize by groups.
1309
+ return [];
1310
+ }
1193
1311
  }