pimath 0.0.66 → 0.0.67

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 (111) hide show
  1. package/.eslintrc.js +23 -23
  2. package/dist/pi.js +178 -44
  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 +14 -14
  35. package/esm/maths/algebra/study/rationalStudy.js.map +1 -1
  36. package/esm/maths/algebra/study.d.ts +9 -22
  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.ts +4 -4
  92. package/src/maths/coefficients/fraction.ts +111 -86
  93. package/src/maths/expressions/expression.ts +191 -0
  94. package/src/maths/expressions/expressionFactor.ts +138 -0
  95. package/src/maths/expressions/expressionMember.ts +114 -0
  96. package/src/maths/expressions/expressionOperators.ts +49 -0
  97. package/src/maths/expressions/expressionParser.ts +249 -0
  98. package/src/maths/expressions/factors/ExpFactor.ts +26 -0
  99. package/src/maths/expressions/factors/ExpFactorConstant.ts +56 -0
  100. package/src/maths/expressions/factors/ExpFactorExponential.ts +19 -0
  101. package/src/maths/expressions/factors/ExpFactorNumber.ts +44 -0
  102. package/src/maths/expressions/factors/ExpFactorPower.ts +24 -0
  103. package/src/maths/expressions/factors/ExpFactorTrigo.ts +44 -0
  104. package/src/maths/expressions/factors/ExpFactorVariable.ts +40 -0
  105. package/src/maths/expressions/internals.ts +14 -0
  106. package/src/maths/shutingyard.ts +156 -26
  107. package/tests/coefficients/fraction.test.ts +17 -0
  108. package/tests/expressions/expressions.test.ts +124 -0
  109. package/tests/shutingyard.test.ts +22 -0
  110. package/.idea/shelf/Uncommitted_changes_before_Update_at_17_04_2022_12_40_[Changes]/shelved.patch +0 -21
  111. 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: [],
@@ -3970,8 +3971,12 @@ const numeric_1 = __webpack_require__(956);
3970
3971
  */
3971
3972
  class Fraction {
3972
3973
  constructor(value, denominatorOrPeriodic) {
3973
- // ------------------------------------------
3974
- // 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
+ };
3975
3980
  // ------------------------------------------
3976
3981
  /**
3977
3982
  * Parse the value to get the numerator and denominator
@@ -3988,15 +3993,15 @@ class Fraction {
3988
3993
  }
3989
3994
  switch (typeof value) {
3990
3995
  case "string":
3991
- // Split the sting value in two parts: Numerator/Denominator
3996
+ // Split the string value in two parts: Numerator/Denominator
3992
3997
  S = value.split('/');
3993
3998
  // Security checks
3994
3999
  if (S.length > 2)
3995
- throw "Two many divide signs";
4000
+ throw value + " has too many divide signs";
3996
4001
  if (S.map(x => x === '' || isNaN(Number(x))).includes(true))
3997
- throw "Not a number";
4002
+ throw value + " is not a valid number";
3998
4003
  if (S.length === 1) {
3999
- // No divide sign
4004
+ // No divide sign - it's a number
4000
4005
  return this.parse(+S[0]);
4001
4006
  }
4002
4007
  else if (S.length === 2) {
@@ -4013,6 +4018,7 @@ class Fraction {
4013
4018
  }
4014
4019
  else {
4015
4020
  // More than one divide sign ?
4021
+ // This is impossible
4016
4022
  this._numerator = NaN;
4017
4023
  this._denominator = 1;
4018
4024
  }
@@ -4053,6 +4059,8 @@ class Fraction {
4053
4059
  }
4054
4060
  return this;
4055
4061
  };
4062
+ // ------------------------------------------
4063
+ // Mathematical operations
4056
4064
  this.clone = () => {
4057
4065
  let F = new Fraction();
4058
4066
  F.numerator = +this._numerator;
@@ -4080,8 +4088,6 @@ class Fraction {
4080
4088
  return this;
4081
4089
  };
4082
4090
  // ------------------------------------------
4083
- // Mathematical operations
4084
- // ------------------------------------------
4085
4091
  this.opposed = () => {
4086
4092
  this._numerator = -this._numerator;
4087
4093
  return this;
@@ -4360,22 +4366,32 @@ class Fraction {
4360
4366
  if (this.isInfinity()) {
4361
4367
  return `${this.sign() === 1 ? '+' : '-'}\\infty`;
4362
4368
  }
4363
- if (this._denominator === 1) {
4364
- return `${this._numerator}`;
4365
- }
4366
- else if (this._numerator < 0) {
4367
- 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
+ }
4368
4379
  }
4369
4380
  else {
4370
- return `\\frac{ ${this._numerator} }{ ${this._denominator} }`;
4381
+ return this.value.toFixed(3);
4371
4382
  }
4372
4383
  }
4373
4384
  get display() {
4374
- if (this._denominator === 1) {
4375
- 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
+ }
4376
4392
  }
4377
4393
  else {
4378
- return `${this._numerator}/${this._denominator}`;
4394
+ return this.value.toFixed(3);
4379
4395
  }
4380
4396
  }
4381
4397
  // Helper function to display fractions
@@ -4410,6 +4426,8 @@ Fraction.min = (...fractions) => {
4410
4426
  }
4411
4427
  return M;
4412
4428
  };
4429
+ // ------------------------------------------
4430
+ // Creation / parsing functions
4413
4431
  Fraction.average = (...fractions) => {
4414
4432
  let M = new Fraction().zero();
4415
4433
  for (let f of fractions) {
@@ -6831,6 +6849,7 @@ var ShutingyardType;
6831
6849
  })(ShutingyardType = exports.ShutingyardType || (exports.ShutingyardType = {}));
6832
6850
  var ShutingyardMode;
6833
6851
  (function (ShutingyardMode) {
6852
+ ShutingyardMode["EXPRESSION"] = "expression";
6834
6853
  ShutingyardMode["POLYNOM"] = "polynom";
6835
6854
  ShutingyardMode["SET"] = "set";
6836
6855
  ShutingyardMode["NUMERIC"] = "numeric";
@@ -6846,6 +6865,9 @@ class Shutingyard {
6846
6865
  // console.log(this._rpn)
6847
6866
  return this._rpn;
6848
6867
  }
6868
+ get rpnToken() {
6869
+ return this._rpn.map(x => x.token);
6870
+ }
6849
6871
  /**
6850
6872
  * Determin if the token is a defined operation
6851
6873
  * Defined operations: + - * / ^ sin cos tan
@@ -6887,6 +6909,22 @@ class Shutingyard {
6887
6909
  };
6888
6910
  this._uniformize = false;
6889
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
+ }
6890
6928
  else {
6891
6929
  this._tokenConfig = {
6892
6930
  '^': { precedence: 4, associative: 'right', type: ShutingyardType.OPERATION },
@@ -6894,10 +6932,6 @@ class Shutingyard {
6894
6932
  '/': { precedence: 3, associative: 'left', type: ShutingyardType.OPERATION },
6895
6933
  '+': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6896
6934
  '-': { precedence: 2, associative: 'left', type: ShutingyardType.OPERATION },
6897
- // '%': {precedence: 3, associative: 'right', type: ShutingyardType.OPERATION},
6898
- // 'sin': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6899
- // 'cos': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6900
- // 'tan': {precedence: 4, associative: 'right', type: ShutingyardType.FUNCTION},
6901
6935
  };
6902
6936
  this._uniformize = true;
6903
6937
  }
@@ -6929,9 +6963,6 @@ class Shutingyard {
6929
6963
  tokenType = 'function-argument';
6930
6964
  }
6931
6965
  else {
6932
- // Order token keys by token characters length (descending)
6933
- // TODO: this is done each time ! SHould be done once !
6934
- // const keys = Object.keys(this._tokenConfig).sort((a,b)=>b.length-a.length)
6935
6966
  // Extract operation and function tokens
6936
6967
  for (let key of this._tokenKeys) {
6937
6968
  if (expr.substring(start, start + key.length) === key) {
@@ -6953,7 +6984,7 @@ class Shutingyard {
6953
6984
  if (expr[start].match(/[0-9]/)) {
6954
6985
  if (this._mode === ShutingyardMode.POLYNOM && false) {}
6955
6986
  else {
6956
- token = expr.substring(start).match(/^([0-9.,]+)/)[0];
6987
+ token = expr.substring(start).match(/^([0-9.]+)/)[0];
6957
6988
  }
6958
6989
  tokenType = ShutingyardType.COEFFICIENT;
6959
6990
  }
@@ -6970,19 +7001,114 @@ class Shutingyard {
6970
7001
  }
6971
7002
  return [token, start + token.length, tokenType];
6972
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
+ }
6973
7082
  /**
6974
7083
  * Sanitize an expression by adding missing common operation (multiplication between parentheseses)
6975
7084
  * @param expr
6976
7085
  * @constructor
6977
7086
  */
6978
7087
  Uniformizer(expr) {
7088
+ // TODO: Delete this old version
7089
+ // Prefere "normalize", much more robust !
6979
7090
  // Determiner if need to be uniformized
6980
7091
  if (!this._uniformize) {
6981
7092
  return expr;
6982
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));
6983
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");
6984
7110
  // Replace missing multiplication between two parenthese
6985
- expr2 = expr.replace(/\)\(/g, ')*(');
7111
+ expr2 = expr2.replace(/\)\(/g, ')*(');
6986
7112
  // Replace missing multiplication between number or setLetter and parenthese.
6987
7113
  // 3x(x-4) => 3x*(x-4)
6988
7114
  expr2 = expr2.replace(/([\da-zA-Z])(\()/g, "$1*$2");
@@ -6992,14 +7118,24 @@ class Shutingyard {
6992
7118
  // 3x => 3*x
6993
7119
  expr2 = expr2.replace(/([0-9])([a-zA-Z])/g, "$1*$2");
6994
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
+ // }
6995
7126
  // Add multiplication between letters ?
6996
- // TODO: More robust solution to handle all letters ?
6997
- expr2 = expr2.replace(/([abcxyz])([abcxyz])/g, "$1*$2");
6998
- // Restore operation auto formating (prevent adding the mutliplcation star)
6999
- // TODO: Accept list of functions
7000
- let fnToken = ['sin', 'cos', 'tan'];
7001
- for (let token of fnToken) {
7002
- 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
+ }
7003
7139
  }
7004
7140
  return expr2;
7005
7141
  }
@@ -7013,7 +7149,9 @@ class Shutingyard {
7013
7149
  let outQueue = [], // Output queue
7014
7150
  opStack = [], // Operation queue
7015
7151
  token = '', tokenPos = 0, tokenType = '', previousOpStatckLength = 0;
7016
- expr = this.Uniformizer(expr);
7152
+ // Normalize the input if required.
7153
+ if (this._uniformize)
7154
+ expr = this.normalize(expr);
7017
7155
  let securityLoopLvl1 = 50, securityLoopLvl2_default = 50, securityLoopLvl2;
7018
7156
  while (tokenPos < expr.length) {
7019
7157
  securityLoopLvl1--;
@@ -7032,10 +7170,6 @@ class Shutingyard {
7032
7170
  token,
7033
7171
  tokenType
7034
7172
  });
7035
- // if(previousOpStatckLength == opStack.length && outQueue.length>=2){
7036
- // console.log('opStatckLength', outQueue, opStack.length)
7037
- // outQueue.push('*')
7038
- // }
7039
7173
  break;
7040
7174
  case 'operation':
7041
7175
  previousOpStatckLength = opStack.length;