pimath 0.0.65 → 0.0.68

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 (113) hide show
  1. package/.eslintrc.js +23 -23
  2. package/dist/pi.js +191 -50
  3. package/dist/pi.js.map +1 -1
  4. package/dist/pi.min.js +1 -1
  5. package/dist/pi.min.js.map +1 -1
  6. package/docs/assets/highlight.css +78 -78
  7. package/docs/assets/main.js +52 -52
  8. package/docs/assets/style.css +1413 -1413
  9. package/docs/classes/Logicalset.Logicalset-1.html +4 -4
  10. package/docs/classes/Polynom.Rational.html +3 -3
  11. package/docs/classes/algebra_equation.Equation.html +25 -25
  12. package/docs/classes/algebra_monom.Monom.html +113 -113
  13. package/docs/classes/algebra_polynom.Polynom.html +29 -29
  14. package/docs/classes/coefficients_fraction.Fraction.html +18 -18
  15. package/docs/classes/coefficients_nthroot.NthRoot.html +2 -2
  16. package/docs/classes/geometry_circle.Circle.html +2 -2
  17. package/docs/classes/geometry_line.Line.html +2 -2
  18. package/docs/classes/geometry_triangle.Triangle.html +16 -16
  19. package/docs/classes/numeric.Numeric.html +13 -13
  20. package/docs/classes/shutingyard.Shutingyard.html +17 -17
  21. package/docs/index.html +10 -10
  22. package/docs/interfaces/algebra_equation.ISolution.html +2 -2
  23. package/docs/modules/Logicalset.html +2 -2
  24. package/docs/modules/Polynom.html +2 -2
  25. package/docs/modules/Vector.html +2 -2
  26. package/esm/maths/algebra/equation.js +2 -2
  27. package/esm/maths/algebra/equation.js.map +1 -1
  28. package/esm/maths/algebra/polynom.d.ts +4 -5
  29. package/esm/maths/algebra/polynom.js +2 -2
  30. package/esm/maths/algebra/polynom.js.map +1 -1
  31. package/esm/maths/algebra/rational.d.ts +8 -10
  32. package/esm/maths/algebra/rational.js +11 -6
  33. package/esm/maths/algebra/study/rationalStudy.d.ts +1 -2
  34. package/esm/maths/algebra/study/rationalStudy.js +25 -17
  35. package/esm/maths/algebra/study/rationalStudy.js.map +1 -1
  36. package/esm/maths/algebra/study.d.ts +13 -30
  37. package/esm/maths/algebra/study.js +33 -23
  38. package/esm/maths/algebra/study.js.map +1 -1
  39. package/esm/maths/coefficients/fraction.d.ts +8 -6
  40. package/esm/maths/coefficients/fraction.js +34 -17
  41. package/esm/maths/coefficients/fraction.js.map +1 -1
  42. package/esm/maths/expressions/expression.d.ts +21 -0
  43. package/esm/maths/expressions/expression.js +161 -0
  44. package/esm/maths/expressions/expression.js.map +1 -0
  45. package/esm/maths/expressions/expressionFactor.d.ts +29 -0
  46. package/esm/maths/expressions/expressionFactor.js +109 -0
  47. package/esm/maths/expressions/expressionFactor.js.map +1 -0
  48. package/esm/maths/expressions/expressionMember.d.ts +16 -0
  49. package/esm/maths/expressions/expressionMember.js +90 -0
  50. package/esm/maths/expressions/expressionMember.js.map +1 -0
  51. package/esm/maths/expressions/expressionOperators.d.ts +8 -0
  52. package/esm/maths/expressions/expressionOperators.js +42 -0
  53. package/esm/maths/expressions/expressionOperators.js.map +1 -0
  54. package/esm/maths/expressions/expressionParser.d.ts +12 -0
  55. package/esm/maths/expressions/expressionParser.js +219 -0
  56. package/esm/maths/expressions/expressionParser.js.map +1 -0
  57. package/esm/maths/expressions/factors/ExpFactor.d.ts +7 -0
  58. package/esm/maths/expressions/factors/ExpFactor.js +22 -0
  59. package/esm/maths/expressions/factors/ExpFactor.js.map +1 -0
  60. package/esm/maths/expressions/factors/ExpFactorConstant.d.ts +13 -0
  61. package/esm/maths/expressions/factors/ExpFactorConstant.js +49 -0
  62. package/esm/maths/expressions/factors/ExpFactorConstant.js.map +1 -0
  63. package/esm/maths/expressions/factors/ExpFactorExponential.d.ts +7 -0
  64. package/esm/maths/expressions/factors/ExpFactorExponential.js +18 -0
  65. package/esm/maths/expressions/factors/ExpFactorExponential.js.map +1 -0
  66. package/esm/maths/expressions/factors/ExpFactorNumber.d.ts +13 -0
  67. package/esm/maths/expressions/factors/ExpFactorNumber.js +36 -0
  68. package/esm/maths/expressions/factors/ExpFactorNumber.js.map +1 -0
  69. package/esm/maths/expressions/factors/ExpFactorPower.d.ts +9 -0
  70. package/esm/maths/expressions/factors/ExpFactorPower.js +22 -0
  71. package/esm/maths/expressions/factors/ExpFactorPower.js.map +1 -0
  72. package/esm/maths/expressions/factors/ExpFactorSin.d.ts +7 -0
  73. package/esm/maths/expressions/factors/ExpFactorSin.js +22 -0
  74. package/esm/maths/expressions/factors/ExpFactorSin.js.map +1 -0
  75. package/esm/maths/expressions/factors/ExpFactorTrigo.d.ts +19 -0
  76. package/esm/maths/expressions/factors/ExpFactorTrigo.js +40 -0
  77. package/esm/maths/expressions/factors/ExpFactorTrigo.js.map +1 -0
  78. package/esm/maths/expressions/factors/ExpFactorVariable.d.ts +12 -0
  79. package/esm/maths/expressions/factors/ExpFactorVariable.js +33 -0
  80. package/esm/maths/expressions/factors/ExpFactorVariable.js.map +1 -0
  81. package/esm/maths/expressions/internals.d.ts +12 -0
  82. package/esm/maths/expressions/internals.js +29 -0
  83. package/esm/maths/expressions/internals.js.map +1 -0
  84. package/esm/maths/shutingyard.d.ts +4 -1
  85. package/esm/maths/shutingyard.js +137 -21
  86. package/esm/maths/shutingyard.js.map +1 -1
  87. package/graph.svg +1033 -0
  88. package/package.json +1 -1
  89. package/src/maths/algebra/equation.ts +2 -2
  90. package/src/maths/algebra/polynom.ts +1 -0
  91. package/src/maths/algebra/study/rationalStudy.ts +18 -7
  92. package/src/maths/algebra/study.ts +5 -4
  93. package/src/maths/coefficients/fraction.ts +111 -86
  94. package/src/maths/expressions/expression.ts +191 -0
  95. package/src/maths/expressions/expressionFactor.ts +138 -0
  96. package/src/maths/expressions/expressionMember.ts +114 -0
  97. package/src/maths/expressions/expressionOperators.ts +49 -0
  98. package/src/maths/expressions/expressionParser.ts +249 -0
  99. package/src/maths/expressions/factors/ExpFactor.ts +26 -0
  100. package/src/maths/expressions/factors/ExpFactorConstant.ts +56 -0
  101. package/src/maths/expressions/factors/ExpFactorExponential.ts +19 -0
  102. package/src/maths/expressions/factors/ExpFactorNumber.ts +44 -0
  103. package/src/maths/expressions/factors/ExpFactorPower.ts +24 -0
  104. package/src/maths/expressions/factors/ExpFactorTrigo.ts +44 -0
  105. package/src/maths/expressions/factors/ExpFactorVariable.ts +40 -0
  106. package/src/maths/expressions/internals.ts +14 -0
  107. package/src/maths/shutingyard.ts +156 -26
  108. package/tests/algebra/study.test.ts +11 -5
  109. package/tests/coefficients/fraction.test.ts +17 -0
  110. package/tests/expressions/expressions.test.ts +124 -0
  111. package/tests/shutingyard.test.ts +22 -0
  112. package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40_[Changes]/shelved.patch +0 -21
  113. package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40__Changes_.xml +0 -4
package/.eslintrc.js CHANGED
@@ -1,24 +1,24 @@
1
- module.exports = {
2
- "env": {
3
- "browser": true,
4
- "es6": true
5
- },
6
- "extends": [
7
- "eslint:recommended",
8
- "plugin:@typescript-eslint/eslint-recommended"
9
- ],
10
- "globals": {
11
- "Atomics": "readonly",
12
- "SharedArrayBuffer": "readonly"
13
- },
14
- "parser": "@typescript-eslint/parser",
15
- "parserOptions": {
16
- "ecmaVersion": 2018,
17
- "sourceType": "module"
18
- },
19
- "plugins": [
20
- "@typescript-eslint"
21
- ],
22
- "rules": {
23
- }
1
+ module.exports = {
2
+ "env": {
3
+ "browser": true,
4
+ "es6": true
5
+ },
6
+ "extends": [
7
+ "eslint:recommended",
8
+ "plugin:@typescript-eslint/eslint-recommended"
9
+ ],
10
+ "globals": {
11
+ "Atomics": "readonly",
12
+ "SharedArrayBuffer": "readonly"
13
+ },
14
+ "parser": "@typescript-eslint/parser",
15
+ "parserOptions": {
16
+ "ecmaVersion": 2018,
17
+ "sourceType": "module"
18
+ },
19
+ "plugins": [
20
+ "@typescript-eslint"
21
+ ],
22
+ "rules": {
23
+ }
24
24
  };
package/dist/pi.js CHANGED
@@ -434,10 +434,10 @@ class Equation {
434
434
  else {
435
435
  // Must handle the case if the m1 monom is negative.
436
436
  if ((this.isGreater() && m1.sign() === 1) || (!this.isGreater() && m1.sign() === -1)) {
437
- s = `\\left${this.isAlsoEqual() ? '\\[' : '\\]'}${v};+\\infty\\right\\[`;
437
+ s = `\\left${this.isAlsoEqual() ? '[' : ']'}${v.tex};+\\infty\\right[`;
438
438
  }
439
439
  else {
440
- s = `\\left\\]-\\infty;${v} \\right\\${this.isAlsoEqual() ? '\\]' : '\\['}`;
440
+ s = `\\left]-\\infty;${v.tex} \\right\\${this.isAlsoEqual() ? ']' : '['}`;
441
441
  }
442
442
  }
443
443
  this._solutions = [{
@@ -2245,6 +2245,7 @@ class Polynom {
2245
2245
  this._monoms = [];
2246
2246
  this._factors = [];
2247
2247
  this.mark_as_dirty();
2248
+ // TODO: allow to enter a liste of Fraction (a, b, c, ...) to make a polynom ax^n + bx^(n-1) + cx^(n-2) + ...
2248
2249
  if (typeof inputStr === 'string') {
2249
2250
  return this._parseString(inputStr, ...values);
2250
2251
  }
@@ -3467,9 +3468,9 @@ var FUNCTION_EXTREMA;
3467
3468
  })(FUNCTION_EXTREMA = exports.FUNCTION_EXTREMA || (exports.FUNCTION_EXTREMA = {}));
3468
3469
  var TABLE_OF_SIGNS;
3469
3470
  (function (TABLE_OF_SIGNS) {
3470
- TABLE_OF_SIGNS[TABLE_OF_SIGNS["DEFAULT"] = 0] = "DEFAULT";
3471
- TABLE_OF_SIGNS[TABLE_OF_SIGNS["GROWS"] = 1] = "GROWS";
3472
- TABLE_OF_SIGNS[TABLE_OF_SIGNS["VARIATIONS"] = 2] = "VARIATIONS";
3471
+ TABLE_OF_SIGNS["SIGNS"] = "signs";
3472
+ TABLE_OF_SIGNS["GROWS"] = "grows";
3473
+ TABLE_OF_SIGNS["VARIATIONS"] = "variatins";
3473
3474
  })(TABLE_OF_SIGNS = exports.TABLE_OF_SIGNS || (exports.TABLE_OF_SIGNS = {}));
3474
3475
  /**
3475
3476
  * The study class is a "function study" class that will get:
@@ -3723,7 +3724,7 @@ class Study {
3723
3724
  ;
3724
3725
  makeSigns() {
3725
3726
  return {
3726
- type: TABLE_OF_SIGNS.DEFAULT,
3727
+ type: TABLE_OF_SIGNS.SIGNS,
3727
3728
  fx: null,
3728
3729
  factors: [],
3729
3730
  zeroes: [],
@@ -3829,21 +3830,23 @@ class RationalStudy extends study_1.Study {
3829
3830
  tex: tex,
3830
3831
  zero: zero,
3831
3832
  limits: `\\lim_{x\\to${zero.tex} }\\ f(x) = \\pm\\infty`,
3832
- deltaX: null
3833
+ deltaX: null,
3834
+ tableOfSign: null
3833
3835
  });
3834
3836
  });
3835
3837
  // Sloped asymptote
3836
3838
  let NDegree = this.fx.numerator.degree(), DDegree = this.fx.denominator.degree();
3837
3839
  if (NDegree.isEqual(DDegree)) {
3838
3840
  let H = this.fx.numerator.monomByDegree().coefficient.clone().divide(this.fx.denominator.monomByDegree().coefficient), Htex = H.tex;
3839
- let { reminder } = reduced.euclidian();
3841
+ let { reminder } = reduced.euclidian(), deltaX = new rational_1.Rational(reminder, reduced.denominator);
3840
3842
  asymptotes.push({
3841
3843
  fx: new polynom_1.Polynom(H),
3842
3844
  type: study_1.ASYMPTOTE.HORIZONTAL,
3843
3845
  tex: `y=${Htex}`,
3844
3846
  zero: null,
3845
3847
  limits: `\\lim_{x\\to\\infty}\\ f(x) = ${Htex}`,
3846
- deltaX: new rational_1.Rational(reminder, reduced.denominator)
3848
+ deltaX,
3849
+ tableOfSign: this._getSigns(deltaX)
3847
3850
  });
3848
3851
  }
3849
3852
  else if (DDegree.greater(NDegree)) {
@@ -3853,19 +3856,21 @@ class RationalStudy extends study_1.Study {
3853
3856
  tex: `y=0`,
3854
3857
  zero: null,
3855
3858
  limits: `\\lim_{x\\to\\infty}\\ f(x) = ${0}`,
3856
- deltaX: null
3859
+ deltaX: null,
3860
+ tableOfSign: null
3857
3861
  });
3858
3862
  }
3859
3863
  else if (NDegree.value - 1 === DDegree.value) {
3860
3864
  // Calculate the slope
3861
- let { quotient, reminder } = reduced.euclidian();
3865
+ let { quotient, reminder } = reduced.euclidian(), deltaX = new rational_1.Rational(reminder, reduced.denominator);
3862
3866
  asymptotes.push({
3863
3867
  fx: quotient.clone(),
3864
3868
  type: study_1.ASYMPTOTE.SLOPE,
3865
3869
  tex: `y=${quotient.tex}`,
3866
3870
  zero: null,
3867
3871
  limits: ``,
3868
- deltaX: new rational_1.Rational(reminder, reduced.denominator)
3872
+ deltaX: new rational_1.Rational(reminder, reduced.denominator),
3873
+ tableOfSign: this._getSigns(deltaX)
3869
3874
  });
3870
3875
  }
3871
3876
  return asymptotes;
@@ -3924,6 +3929,9 @@ class RationalStudy extends study_1.Study {
3924
3929
  _getSigns(fx, zeroes, typeOfTable) {
3925
3930
  // Factorize the rational
3926
3931
  let signs = [], factors = [];
3932
+ if (zeroes === undefined) {
3933
+ zeroes = this._getZeroes(fx);
3934
+ }
3927
3935
  fx.numerator.factors.forEach(factor => {
3928
3936
  signs.push(this.makeOneLineForSigns(factor, zeroes, study_1.ZEROTYPE.ZERO));
3929
3937
  factors.push(factor.clone());
@@ -3963,8 +3971,12 @@ const numeric_1 = __webpack_require__(956);
3963
3971
  */
3964
3972
  class Fraction {
3965
3973
  constructor(value, denominatorOrPeriodic) {
3966
- // ------------------------------------------
3967
- // Creation / parsing functions
3974
+ this.isApproximative = () => {
3975
+ return this._numerator.toString().length >= 15 && this._denominator.toString().length >= 15;
3976
+ };
3977
+ this.isExact = () => {
3978
+ return !this.isApproximative();
3979
+ };
3968
3980
  // ------------------------------------------
3969
3981
  /**
3970
3982
  * Parse the value to get the numerator and denominator
@@ -3981,15 +3993,15 @@ class Fraction {
3981
3993
  }
3982
3994
  switch (typeof value) {
3983
3995
  case "string":
3984
- // Split the sting value in two parts: Numerator/Denominator
3996
+ // Split the string value in two parts: Numerator/Denominator
3985
3997
  S = value.split('/');
3986
3998
  // Security checks
3987
3999
  if (S.length > 2)
3988
- throw "Two many divide signs";
4000
+ throw value + " has too many divide signs";
3989
4001
  if (S.map(x => x === '' || isNaN(Number(x))).includes(true))
3990
- throw "Not a number";
4002
+ throw value + " is not a valid number";
3991
4003
  if (S.length === 1) {
3992
- // No divide sign
4004
+ // No divide sign - it's a number
3993
4005
  return this.parse(+S[0]);
3994
4006
  }
3995
4007
  else if (S.length === 2) {
@@ -4006,6 +4018,7 @@ class Fraction {
4006
4018
  }
4007
4019
  else {
4008
4020
  // More than one divide sign ?
4021
+ // This is impossible
4009
4022
  this._numerator = NaN;
4010
4023
  this._denominator = 1;
4011
4024
  }
@@ -4046,6 +4059,8 @@ class Fraction {
4046
4059
  }
4047
4060
  return this;
4048
4061
  };
4062
+ // ------------------------------------------
4063
+ // Mathematical operations
4049
4064
  this.clone = () => {
4050
4065
  let F = new Fraction();
4051
4066
  F.numerator = +this._numerator;
@@ -4073,8 +4088,6 @@ class Fraction {
4073
4088
  return this;
4074
4089
  };
4075
4090
  // ------------------------------------------
4076
- // Mathematical operations
4077
- // ------------------------------------------
4078
4091
  this.opposed = () => {
4079
4092
  this._numerator = -this._numerator;
4080
4093
  return this;
@@ -4353,22 +4366,32 @@ class Fraction {
4353
4366
  if (this.isInfinity()) {
4354
4367
  return `${this.sign() === 1 ? '+' : '-'}\\infty`;
4355
4368
  }
4356
- if (this._denominator === 1) {
4357
- return `${this._numerator}`;
4358
- }
4359
- else if (this._numerator < 0) {
4360
- return `-\\frac{ ${-this._numerator} }{ ${this._denominator} }`;
4369
+ if (this.isExact()) {
4370
+ if (this._denominator === 1) {
4371
+ return `${this._numerator}`;
4372
+ }
4373
+ else if (this._numerator < 0) {
4374
+ return `-\\frac{ ${-this._numerator} }{ ${this._denominator} }`;
4375
+ }
4376
+ else {
4377
+ return `\\frac{ ${this._numerator} }{ ${this._denominator} }`;
4378
+ }
4361
4379
  }
4362
4380
  else {
4363
- return `\\frac{ ${this._numerator} }{ ${this._denominator} }`;
4381
+ return this.value.toFixed(3);
4364
4382
  }
4365
4383
  }
4366
4384
  get display() {
4367
- if (this._denominator === 1) {
4368
- return `${this._numerator}`;
4385
+ if (this.isExact()) {
4386
+ if (this._denominator === 1) {
4387
+ return `${this._numerator}`;
4388
+ }
4389
+ else {
4390
+ return `${this._numerator}/${this._denominator}`;
4391
+ }
4369
4392
  }
4370
4393
  else {
4371
- return `${this._numerator}/${this._denominator}`;
4394
+ return this.value.toFixed(3);
4372
4395
  }
4373
4396
  }
4374
4397
  // Helper function to display fractions
@@ -4403,6 +4426,8 @@ Fraction.min = (...fractions) => {
4403
4426
  }
4404
4427
  return M;
4405
4428
  };
4429
+ // ------------------------------------------
4430
+ // Creation / parsing functions
4406
4431
  Fraction.average = (...fractions) => {
4407
4432
  let M = new Fraction().zero();
4408
4433
  for (let f of fractions) {
@@ -6824,6 +6849,7 @@ var ShutingyardType;
6824
6849
  })(ShutingyardType = exports.ShutingyardType || (exports.ShutingyardType = {}));
6825
6850
  var ShutingyardMode;
6826
6851
  (function (ShutingyardMode) {
6852
+ ShutingyardMode["EXPRESSION"] = "expression";
6827
6853
  ShutingyardMode["POLYNOM"] = "polynom";
6828
6854
  ShutingyardMode["SET"] = "set";
6829
6855
  ShutingyardMode["NUMERIC"] = "numeric";
@@ -6839,6 +6865,9 @@ class Shutingyard {
6839
6865
  // console.log(this._rpn)
6840
6866
  return this._rpn;
6841
6867
  }
6868
+ get rpnToken() {
6869
+ return this._rpn.map(x => x.token);
6870
+ }
6842
6871
  /**
6843
6872
  * Determin if the token is a defined operation
6844
6873
  * Defined operations: + - * / ^ sin cos tan
@@ -6880,6 +6909,22 @@ class Shutingyard {
6880
6909
  };
6881
6910
  this._uniformize = false;
6882
6911
  }
6912
+ else if (this._mode === ShutingyardMode.EXPRESSION) {
6913
+ this._tokenConfig = {
6914
+ '^': { precedence: 4, associative: 'right', type: ShutingyardType.OPERATION },
6915
+ '*': { precedence: 3, associative: 'left', type: ShutingyardType.OPERATION },
6916
+ '/': { precedence: 3, associative: 'left', type: ShutingyardType.OPERATION },
6917
+ '+': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6918
+ '-': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6919
+ '%': { precedence: 3, associative: 'right', type: ShutingyardType.OPERATION },
6920
+ 'sin': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6921
+ 'cos': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6922
+ 'tan': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6923
+ 'sqrt': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6924
+ 'nthrt': { precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION },
6925
+ };
6926
+ this._uniformize = true;
6927
+ }
6883
6928
  else {
6884
6929
  this._tokenConfig = {
6885
6930
  '^': { precedence: 4, associative: 'right', type: ShutingyardType.OPERATION },
@@ -6887,10 +6932,6 @@ class Shutingyard {
6887
6932
  '/': { precedence: 3, associative: 'left', type: ShutingyardType.OPERATION },
6888
6933
  '+': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6889
6934
  '-': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6890
- // '%': {precedence: 3, associative: 'right', type: ShutingyardType.OPERATION},
6891
- // 'sin': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6892
- // 'cos': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6893
- // 'tan': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6894
6935
  };
6895
6936
  this._uniformize = true;
6896
6937
  }
@@ -6922,9 +6963,6 @@ class Shutingyard {
6922
6963
  tokenType = 'function-argument';
6923
6964
  }
6924
6965
  else {
6925
- // Order token keys by token characters length (descending)
6926
- // TODO: this is done each time ! SHould be done once !
6927
- // const keys = Object.keys(this._tokenConfig).sort((a,b)=>b.length-a.length)
6928
6966
  // Extract operation and function tokens
6929
6967
  for (let key of this._tokenKeys) {
6930
6968
  if (expr.substring(start, start + key.length) === key) {
@@ -6946,7 +6984,7 @@ class Shutingyard {
6946
6984
  if (expr[start].match(/[0-9]/)) {
6947
6985
  if (this._mode === ShutingyardMode.POLYNOM && false) {}
6948
6986
  else {
6949
- token = expr.substring(start).match(/^([0-9.,]+)/)[0];
6987
+ token = expr.substring(start).match(/^([0-9.]+)/)[0];
6950
6988
  }
6951
6989
  tokenType = ShutingyardType.COEFFICIENT;
6952
6990
  }
@@ -6963,19 +7001,114 @@ class Shutingyard {
6963
7001
  }
6964
7002
  return [token, start + token.length, tokenType];
6965
7003
  }
7004
+ normalize(expr) {
7005
+ // Get the list of function token.
7006
+ let fnToken = [], kToken = [];
7007
+ for (let token in this._tokenConfig) {
7008
+ if (this._tokenConfig[token].type === ShutingyardType.FUNCTION) {
7009
+ fnToken.push(token);
7010
+ }
7011
+ }
7012
+ // sort if from the lengthy to the smallest function
7013
+ fnToken.sort((a, b) => b.length - a.length);
7014
+ for (let token in exports.tokenConstant) {
7015
+ kToken.push(token);
7016
+ }
7017
+ // sort if from the lengthy to the smallest function
7018
+ kToken.sort((a, b) => b.length - a.length);
7019
+ let normalizedExpr = "", i = 0, crtToken, nextToken;
7020
+ while (i < expr.length - 1) {
7021
+ // Check if we have a function token.
7022
+ // The function MUST have an open parentheses
7023
+ let tokenIdx = 0;
7024
+ while (tokenIdx < fnToken.length) {
7025
+ let token = fnToken[tokenIdx];
7026
+ if (expr.slice(i, i + token.length + 1) === token + '(') {
7027
+ normalizedExpr += token + '(';
7028
+ i += token.length + 1;
7029
+ // Restart the scan for the function token
7030
+ tokenIdx = 0;
7031
+ }
7032
+ else {
7033
+ // scan for a next function token
7034
+ tokenIdx++;
7035
+ }
7036
+ }
7037
+ // Check for a constant
7038
+ tokenIdx = 0;
7039
+ while (tokenIdx < kToken.length) {
7040
+ let token = kToken[tokenIdx];
7041
+ if (expr.slice(i, i + token.length) === token) {
7042
+ // We have found a constant.
7043
+ // add it, but with remove the last letter
7044
+ normalizedExpr += token.slice(0, -1);
7045
+ i += token.length - 1;
7046
+ // Exit the loop
7047
+ break;
7048
+ }
7049
+ tokenIdx++;
7050
+ }
7051
+ // The function token are solved.
7052
+ crtToken = expr[i];
7053
+ nextToken = expr[i + 1];
7054
+ normalizedExpr += crtToken;
7055
+ if (crtToken.match(/[a-zA-Z]/g)) {
7056
+ // Current element is a letter.
7057
+ // if the next element is a letter, a number or an opening parentheses, add the multiplication sign.
7058
+ if (nextToken.match(/[a-zA-Z\d(]/)) {
7059
+ normalizedExpr += '*';
7060
+ }
7061
+ }
7062
+ else if (crtToken.match(/\d/)) {
7063
+ // Current element is a number.
7064
+ // if the next element is a letter or a parentheses, add the multiplication sign.
7065
+ if (nextToken.match(/[a-zA-Z(]/)) {
7066
+ normalizedExpr += '*';
7067
+ }
7068
+ }
7069
+ else if (crtToken === ')') {
7070
+ // Current element is a closing parentheses.
7071
+ // if the next element is a letter, a number or an opening parentheses, add the multiplication sign
7072
+ if (nextToken.match(/[a-zA-Z\d(]/)) {
7073
+ normalizedExpr += '*';
7074
+ }
7075
+ }
7076
+ // Go to next token
7077
+ i++;
7078
+ }
7079
+ // add the last token
7080
+ return normalizedExpr + nextToken;
7081
+ }
6966
7082
  /**
6967
7083
  * Sanitize an expression by adding missing common operation (multiplication between parentheseses)
6968
7084
  * @param expr
6969
7085
  * @constructor
6970
7086
  */
6971
7087
  Uniformizer(expr) {
7088
+ // TODO: Delete this old version
7089
+ // Prefere "normalize", much more robust !
6972
7090
  // Determiner if need to be uniformized
6973
7091
  if (!this._uniformize) {
6974
7092
  return expr;
6975
7093
  }
7094
+ // Generate the list of function token.
7095
+ let fnToken = [];
7096
+ for (let token in this._tokenConfig) {
7097
+ if (this._tokenConfig[token].type === ShutingyardType.FUNCTION) {
7098
+ fnToken.push(token);
7099
+ }
7100
+ }
7101
+ // sort if from the lengthy to the smallest function
7102
+ fnToken.sort((a, b) => b.length - a.length);
7103
+ let tokenRegExp = new RegExp(`(${fnToken.join('|')})`, 'g');
7104
+ let functionTokenOrder = Array.from(expr.matchAll(tokenRegExp));
6976
7105
  let expr2;
7106
+ // Replace all function by @
7107
+ expr2 = expr.replace(tokenRegExp, '@');
7108
+ // Add * before @ (functionn)
7109
+ expr2 = expr2.replace(/([\da-zA-Z])(@)/g, "$1*$2");
6977
7110
  // Replace missing multiplication between two parenthese
6978
- expr2 = expr.replace(/\)\(/g, ')*(');
7111
+ expr2 = expr2.replace(/\)\(/g, ')*(');
6979
7112
  // Replace missing multiplication between number or setLetter and parenthese.
6980
7113
  // 3x(x-4) => 3x*(x-4)
6981
7114
  expr2 = expr2.replace(/([\da-zA-Z])(\()/g, "$1*$2");
@@ -6985,14 +7118,24 @@ class Shutingyard {
6985
7118
  // 3x => 3*x
6986
7119
  expr2 = expr2.replace(/([0-9])([a-zA-Z])/g, "$1*$2");
6987
7120
  expr2 = expr2.replace(/([a-zA-Z])([0-9])/g, "$1*$2");
7121
+ // Remove letter between function token and it's parenthese.
7122
+ // for (let token of fnToken) {
7123
+ // // Remove
7124
+ // expr2 = expr2.replace(new RegExp(token + '\\*', 'g'), token);
7125
+ // }
6988
7126
  // Add multiplication between letters ?
6989
- // TODO: More robust solution to handle all letters ?
6990
- expr2 = expr2.replace(/([abcxyz])([abcxyz])/g, "$1*$2");
6991
- // Restore operation auto formating (prevent adding the mutliplcation star)
6992
- // TODO: Accept list of functions
6993
- let fnToken = ['sin', 'cos', 'tan'];
6994
- for (let token of fnToken) {
6995
- expr2 = expr2.replace(new RegExp(token + '\\*', 'g'), token);
7127
+ expr2 = expr2.replace(/([a-zA-Z])([a-zA-Z])/g, "$1*$2");
7128
+ expr2 = expr2.replace(/([a-zA-Z])([a-zA-Z])/g, "$1*$2");
7129
+ // Restore operation auto formatting (prevent adding the multiplication star)
7130
+ let exprAsArray = expr2.split('@');
7131
+ if (exprAsArray.length > 0) {
7132
+ expr2 = "";
7133
+ for (let idx in exprAsArray) {
7134
+ }
7135
+ for (let token of fnToken) {
7136
+ // Remove
7137
+ // expr2 = expr2.replace(new RegExp(token + '\\*', 'g'), token);
7138
+ }
6996
7139
  }
6997
7140
  return expr2;
6998
7141
  }
@@ -7006,7 +7149,9 @@ class Shutingyard {
7006
7149
  let outQueue = [], // Output queue
7007
7150
  opStack = [], // Operation queue
7008
7151
  token = '', tokenPos = 0, tokenType = '', previousOpStatckLength = 0;
7009
- expr = this.Uniformizer(expr);
7152
+ // Normalize the input if required.
7153
+ if (this._uniformize)
7154
+ expr = this.normalize(expr);
7010
7155
  let securityLoopLvl1 = 50, securityLoopLvl2_default = 50, securityLoopLvl2;
7011
7156
  while (tokenPos < expr.length) {
7012
7157
  securityLoopLvl1--;
@@ -7025,10 +7170,6 @@ class Shutingyard {
7025
7170
  token,
7026
7171
  tokenType
7027
7172
  });
7028
- // if(previousOpStatckLength == opStack.length && outQueue.length>=2){
7029
- // console.log('opStatckLength', outQueue, opStack.length)
7030
- // outQueue.push('*')
7031
- // }
7032
7173
  break;
7033
7174
  case 'operation':
7034
7175
  previousOpStatckLength = opStack.length;