pimath 0.2.11 → 0.2.13

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 (57) hide show
  1. package/dist/pimath.js +882 -907
  2. package/dist/pimath.js.map +1 -1
  3. package/package.json +3 -2
  4. package/src/algebra/equation.ts +3 -2
  5. package/src/algebra/equationSolver.ts +2 -1
  6. package/src/algebra/factor.ts +10 -9
  7. package/src/algebra/linearSystem.ts +10 -9
  8. package/src/algebra/logicalset.ts +8 -3
  9. package/src/algebra/matrix.ts +10 -9
  10. package/src/algebra/monom.ts +10 -4
  11. package/src/algebra/operations.ts +3 -2
  12. package/src/algebra/polyFactor.ts +5 -4
  13. package/src/algebra/polynom.ts +30 -30
  14. package/src/coefficients/fraction.ts +6 -5
  15. package/src/coefficients/root.ts +5 -4
  16. package/src/errors.ts +45 -0
  17. package/src/geometry/TupleN.ts +4 -3
  18. package/src/geometry/geomMath.ts +3 -2
  19. package/src/geometry/line.ts +4 -2
  20. package/src/geometry/line3.ts +7 -6
  21. package/src/geometry/plane3.ts +3 -2
  22. package/src/geometry/point.ts +5 -4
  23. package/src/geometry/sphere3.ts +6 -5
  24. package/src/geometry/triangle.ts +3 -2
  25. package/src/geometry/vector.ts +6 -5
  26. package/src/helpers.ts +3 -1
  27. package/src/index.ts +23 -0
  28. package/src/numeric.ts +2 -1
  29. package/src/randomization/rndHelpers.ts +2 -1
  30. package/types/algebra/equation.d.ts.map +1 -1
  31. package/types/algebra/equationSolver.d.ts.map +1 -1
  32. package/types/algebra/factor.d.ts.map +1 -1
  33. package/types/algebra/linearSystem.d.ts.map +1 -1
  34. package/types/algebra/logicalset.d.ts.map +1 -1
  35. package/types/algebra/matrix.d.ts.map +1 -1
  36. package/types/algebra/monom.d.ts.map +1 -1
  37. package/types/algebra/operations.d.ts.map +1 -1
  38. package/types/algebra/polyFactor.d.ts.map +1 -1
  39. package/types/algebra/polynom.d.ts.map +1 -1
  40. package/types/coefficients/fraction.d.ts.map +1 -1
  41. package/types/coefficients/root.d.ts.map +1 -1
  42. package/types/errors.d.ts +20 -0
  43. package/types/errors.d.ts.map +1 -0
  44. package/types/geometry/TupleN.d.ts.map +1 -1
  45. package/types/geometry/geomMath.d.ts.map +1 -1
  46. package/types/geometry/line.d.ts.map +1 -1
  47. package/types/geometry/line3.d.ts.map +1 -1
  48. package/types/geometry/plane3.d.ts.map +1 -1
  49. package/types/geometry/point.d.ts.map +1 -1
  50. package/types/geometry/sphere3.d.ts.map +1 -1
  51. package/types/geometry/triangle.d.ts.map +1 -1
  52. package/types/geometry/vector.d.ts.map +1 -1
  53. package/types/helpers.d.ts.map +1 -1
  54. package/types/index.d.ts +12 -0
  55. package/types/index.d.ts.map +1 -1
  56. package/types/numeric.d.ts.map +1 -1
  57. package/types/randomization/rndHelpers.d.ts.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pimath",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "description": "A math library for teacher :)",
5
5
  "type": "module",
6
6
  "main": "dist/pimath.js",
@@ -39,6 +39,7 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "@tailwindcss/vite": "^4.3.3",
42
+ "@eslint/js": "^10.0.1",
42
43
  "@types/eslint": "^9.6.1",
43
44
  "@vitejs/plugin-vue": "^6.0.8",
44
45
  "autoprefixer": "^10.5.4",
@@ -56,6 +57,6 @@
56
57
  "vue-router": "^5.2.0"
57
58
  },
58
59
  "dependencies": {
59
- "piexpression": "^0.1.4"
60
+ "piexpression": "^0.1.5"
60
61
  }
61
62
  }
@@ -9,6 +9,7 @@ import type {
9
9
  } from "../pimath.interface"
10
10
  import {Fraction} from "../coefficients"
11
11
  import {Numeric} from "../numeric"
12
+ import {ParseError} from "../errors"
12
13
  import {EquationSolver} from "./equationSolver"
13
14
  import {Monom} from "./monom"
14
15
  import {Polynom} from "./polynom"
@@ -62,7 +63,7 @@ export class Equation implements IPiMathObject<Equation>,
62
63
  const strSign: string | false = this.#findSign(equationString)
63
64
 
64
65
  if (strSign === false) {
65
- throw new Error('The equation is not valid (no sign found)')
66
+ throw new ParseError('The equation is not valid (no sign found)')
66
67
  }
67
68
 
68
69
  // The StrSign is found
@@ -507,7 +508,7 @@ export class Equation implements IPiMathObject<Equation>,
507
508
  return '='
508
509
  }
509
510
 
510
- throw new Error('The equation is not valid (no sign found)')
511
+ throw new ParseError('The equation is not valid (no sign found)')
511
512
  }
512
513
 
513
514
  // -----------------------------------------------
@@ -4,6 +4,7 @@ import {Fraction} from "../coefficients"
4
4
  import {Numeric} from "../numeric"
5
5
  import type {Equation} from "./equation"
6
6
  import {Solution} from "../analyze"
7
+ import {MathError} from "../errors"
7
8
 
8
9
  export class EquationSolver {
9
10
  _: number
@@ -78,7 +79,7 @@ export class EquationSolver {
78
79
 
79
80
  public solveAsCardan(): Solution[] {
80
81
  if (this.#leftPolynom.degree().value !== 3) {
81
- throw new Error("The equation is not cubic.")
82
+ throw new MathError("The equation is not cubic.")
82
83
  }
83
84
  return this.#solveCubic_CardanFormula()
84
85
  }
@@ -10,6 +10,7 @@ import type {
10
10
  import {Fraction} from "../coefficients/fraction"
11
11
  import {Polynom} from "./polynom"
12
12
  import {replace_in_array, splitIfOutsideParentheses, wrapParenthesis} from "../helpers"
13
+ import {MathError, NotImplementedError} from "../errors"
13
14
 
14
15
  export class Factor implements IPiMathObject<Factor>,
15
16
  IExpression<Factor>,
@@ -42,7 +43,7 @@ export class Factor implements IPiMathObject<Factor>,
42
43
  }
43
44
 
44
45
  public parse(/*value: InputValue<Factor>*/): Factor {
45
- throw new Error("Method not implemented.")
46
+ throw new NotImplementedError("Method not implemented.")
46
47
  }
47
48
 
48
49
  public clone(): Factor {
@@ -104,7 +105,7 @@ export class Factor implements IPiMathObject<Factor>,
104
105
  }
105
106
 
106
107
  public add(): Factor {
107
- throw new Error("Adding two factors is not possible")
108
+ throw new MathError("Adding two factors is not possible")
108
109
  }
109
110
 
110
111
  public get asSingle(): this {
@@ -141,7 +142,7 @@ export class Factor implements IPiMathObject<Factor>,
141
142
  return this.polynom.clone().pow(this.power.value)
142
143
  }
143
144
 
144
- throw new Error("The power must be a natural number")
145
+ throw new MathError("The power must be a natural number")
145
146
  }
146
147
 
147
148
  public divide(value: InputAlgebra<Factor | Polynom>): this {
@@ -159,7 +160,7 @@ export class Factor implements IPiMathObject<Factor>,
159
160
  return this
160
161
  }
161
162
 
162
- throw new Error("The two factors must be the same")
163
+ throw new MathError("The two factors must be the same")
163
164
  }
164
165
 
165
166
  public evaluate(values: InputValue<Fraction> | literalType<number | Fraction>, asNumeric?: boolean): number | Fraction {
@@ -241,7 +242,7 @@ export class Factor implements IPiMathObject<Factor>,
241
242
  return this
242
243
  }
243
244
 
244
- throw new Error("The two factors must be the same")
245
+ throw new MathError("The two factors must be the same")
245
246
  }
246
247
 
247
248
  public one(): this {
@@ -251,7 +252,7 @@ export class Factor implements IPiMathObject<Factor>,
251
252
  }
252
253
 
253
254
  public opposite(): Factor {
254
- throw new Error("Method not implemented.")
255
+ throw new NotImplementedError("Method not implemented.")
255
256
  }
256
257
 
257
258
  public get polynom(): Polynom {
@@ -276,11 +277,11 @@ export class Factor implements IPiMathObject<Factor>,
276
277
  }
277
278
 
278
279
  public primitive(): Factor {
279
- throw new Error("Method not implemented.")
280
+ throw new NotImplementedError("Method not implemented.")
280
281
  }
281
282
 
282
283
  public reduce(): Factor {
283
- throw new Error("Method not implemented.")
284
+ throw new NotImplementedError("Method not implemented.")
284
285
  }
285
286
 
286
287
  public root(value: number): this {
@@ -293,7 +294,7 @@ export class Factor implements IPiMathObject<Factor>,
293
294
  }
294
295
 
295
296
  public subtract(): Factor {
296
- throw new Error("Subtracting two factors is not possible")
297
+ throw new MathError("Subtracting two factors is not possible")
297
298
  }
298
299
 
299
300
  public tableOfSigns(): TABLE_OF_SIGNS {
@@ -5,6 +5,7 @@ import {Monom} from "./monom"
5
5
  import {Polynom} from "./polynom"
6
6
  import {Numeric} from "../numeric"
7
7
  import {Solution} from "../analyze"
8
+ import {DimensionError, IndexError, MathError, NotImplementedError} from "../errors"
8
9
 
9
10
  export class LinearSystem implements IPiMathObject<LinearSystem>,
10
11
  IEquation<LinearSystem>,
@@ -61,7 +62,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
61
62
  // Check that each row has the same number of columns
62
63
  const cols = matrix[0].length
63
64
  if (matrix.some(row => row.length !== cols)) {
64
- throw new Error("All rows must have the same number of columns")
65
+ throw new DimensionError("All rows must have the same number of columns")
65
66
  }
66
67
 
67
68
  // Determine the default letters. The number of letters are cols-1
@@ -88,7 +89,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
88
89
  if (value instanceof LinearSystem) {
89
90
  const length = value.equations.length
90
91
  if (length !== this.#equations.length) {
91
- throw new Error("The number of equations must be the same")
92
+ throw new DimensionError("The number of equations must be the same")
92
93
  }
93
94
 
94
95
  for (let i = 0; i < length; i++) {
@@ -96,7 +97,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
96
97
  }
97
98
  } else {
98
99
  if (index === undefined || index < 0 || index >= this.#equations.length) {
99
- throw new Error("Index out of range")
100
+ throw new IndexError("Index out of range")
100
101
  }
101
102
  const equ = new Equation(value)
102
103
  this.#equations[index].add(equ)
@@ -177,7 +178,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
177
178
  }
178
179
 
179
180
  public evaluate(values: InputValue<Fraction> | literalType<number | Fraction>, asNumeric?: boolean): number | Fraction {
180
- throw new Error("Method not implemented.")
181
+ throw new NotImplementedError("Method not implemented.")
181
182
  }
182
183
 
183
184
  public hasVariable(letter: string): boolean {
@@ -224,7 +225,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
224
225
  // the value can be a number and the index of the equation to multiply
225
226
  if (Array.isArray(value)) {
226
227
  if (value.length !== this.#equations.length) {
227
- throw new Error("The number of values must be the same as the number of equations")
228
+ throw new DimensionError("The number of values must be the same as the number of equations")
228
229
  }
229
230
 
230
231
  for (let i = 0; i < value.length; i++) {
@@ -234,7 +235,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
234
235
  }
235
236
 
236
237
  if (index === undefined || index < 0 || index >= this.#equations.length) {
237
- throw new Error("Index out of range")
238
+ throw new IndexError("Index out of range")
238
239
  }
239
240
 
240
241
  this.#equations[index].multiply(value)
@@ -280,7 +281,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
280
281
  augmentedMatrix[i].forEach((value, index) => value.add(row_to_add[index]))
281
282
  pivot = augmentedMatrix[i][i].clone()
282
283
  } else {
283
- throw new Error('Unsolvable...')
284
+ throw new MathError('Unsolvable...')
284
285
  }
285
286
 
286
287
 
@@ -353,7 +354,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
353
354
  if (value instanceof LinearSystem) {
354
355
  const length = value.equations.length
355
356
  if (length !== this.#equations.length) {
356
- throw new Error("The number of equations must be the same")
357
+ throw new DimensionError("The number of equations must be the same")
357
358
  }
358
359
 
359
360
  for (let i = 0; i < length; i++) {
@@ -361,7 +362,7 @@ export class LinearSystem implements IPiMathObject<LinearSystem>,
361
362
  }
362
363
  } else {
363
364
  if (index === undefined || index < 0 || index >= this.#equations.length) {
364
- throw new Error("Index out of range")
365
+ throw new IndexError("Index out of range")
365
366
  }
366
367
  const equ = new Equation(value)
367
368
  this.#equations[index].subtract(equ)
@@ -3,6 +3,7 @@
3
3
  * @module Logicalset
4
4
  */
5
5
  import {ShutingYard, ShutingyardMode} from "piexpression"
6
+ import {ParseError} from "../errors"
6
7
 
7
8
  /**
8
9
  * Polynom class can handle polynoms, reorder, resolve, ...
@@ -26,9 +27,13 @@ export class LogicalSet {
26
27
 
27
28
  parse = (value: string): this => {
28
29
  // Parse the updated value to the shutingyard algorithm
29
- this.#rpn = new ShutingYard(ShutingyardMode.SET)
30
- .parse(value)
31
- .rpn
30
+ try {
31
+ this.#rpn = new ShutingYard(ShutingyardMode.SET)
32
+ .parse(value)
33
+ .rpn
34
+ } catch (e) {
35
+ throw new ParseError(`Cannot parse "${value}" as a LogicalSet`, {cause: e})
36
+ }
32
37
 
33
38
  return this
34
39
  }
@@ -2,6 +2,7 @@ import type {IExpressionMultiply, InputAlgebra, InputValue, IPiMathObject} from
2
2
  import {Polynom} from "./polynom"
3
3
  import type {Vector} from "../geometry"
4
4
  import {operation_pow} from "./operations"
5
+ import {DimensionError, IndexError, MathError, NotImplementedError} from "../errors"
5
6
 
6
7
  export type IMatrixValues = InputAlgebra<Polynom>[][]
7
8
 
@@ -107,7 +108,7 @@ export class Matrix implements IPiMathObject<Matrix>,
107
108
 
108
109
  public add(value: Matrix): this {
109
110
  if (!this.canBeAdded(value)) {
110
- throw new Error("Cannot add a matrix with different dimensions.")
111
+ throw new DimensionError("Cannot add a matrix with different dimensions.")
111
112
  }
112
113
  this.forEach((aij, i, j) => {
113
114
  aij.add(value.values[i][j])
@@ -195,7 +196,7 @@ export class Matrix implements IPiMathObject<Matrix>,
195
196
 
196
197
  public determinant(): Polynom {
197
198
  if (!this.isSquare()) {
198
- throw new Error('Matrix is not square')
199
+ throw new DimensionError('Matrix is not square')
199
200
  }
200
201
 
201
202
  // Use the first line.
@@ -276,7 +277,7 @@ export class Matrix implements IPiMathObject<Matrix>,
276
277
  // Check dimensions of each rows.
277
278
  const L = values[0].length
278
279
  if (values.some(row => row.length !== L)) {
279
- throw new Error("Each line must be the same length")
280
+ throw new DimensionError("Each line must be the same length")
280
281
  }
281
282
 
282
283
  values.forEach(row => {
@@ -298,7 +299,7 @@ export class Matrix implements IPiMathObject<Matrix>,
298
299
  // Each vectors must be the same dimension
299
300
  const L = vectors[0].dimension
300
301
  if (vectors.some(v => v.dimension !== L)) {
301
- throw new Error("Each vectors must be the same dimension")
302
+ throw new DimensionError("Each vectors must be the same dimension")
302
303
  }
303
304
 
304
305
  this.fromDimensions(vectors[0].dimension, vectors.length)
@@ -314,7 +315,7 @@ export class Matrix implements IPiMathObject<Matrix>,
314
315
 
315
316
  public inverse(): this {
316
317
  if (!this.canBeInverted()) {
317
- throw new Error('The matrix cannot be inverted.')
318
+ throw new MathError('The matrix cannot be inverted.')
318
319
  }
319
320
 
320
321
  const cofactors_matrix = new Matrix().fromDimensions(this.dimension.rows, this.dimension.cols)
@@ -387,7 +388,7 @@ export class Matrix implements IPiMathObject<Matrix>,
387
388
  public multiply(value: InputValue<Polynom> | Matrix): this {
388
389
  if (value instanceof Matrix) {
389
390
  if (!this.canBeMultiplied(value)) {
390
- throw new Error(`Cannot multiply a matrix with incompatibles dimensions`)
391
+ throw new DimensionError(`Cannot multiply a matrix with incompatibles dimensions`)
391
392
  }
392
393
 
393
394
  // Multiply two matrix
@@ -455,7 +456,7 @@ export class Matrix implements IPiMathObject<Matrix>,
455
456
  }
456
457
 
457
458
  public reduce(): Matrix {
458
- throw new Error('Not yet implemented')
459
+ throw new NotImplementedError('Not yet implemented')
459
460
  }
460
461
 
461
462
  get rows(): Polynom[][] {
@@ -466,7 +467,7 @@ export class Matrix implements IPiMathObject<Matrix>,
466
467
  const {rows, cols} = this.dimension
467
468
  if ((row < 0 || row >= rows) ||
468
469
  column < 0 || column >= cols) {
469
- throw new Error(`${row}x${column} is out of range (${rows}x${cols})`)
470
+ throw new IndexError(`${row}x${column} is out of range (${rows}x${cols})`)
470
471
  }
471
472
 
472
473
  this.#values[row][column] = new Polynom(value)
@@ -475,7 +476,7 @@ export class Matrix implements IPiMathObject<Matrix>,
475
476
 
476
477
  public subtract(value: Matrix): this {
477
478
  if (!this.canBeAdded(value)) {
478
- throw new Error("Cannot subtract a matrix with different dimensions.")
479
+ throw new DimensionError("Cannot subtract a matrix with different dimensions.")
479
480
  }
480
481
 
481
482
  this.forEach((aij, i, j) => {
@@ -14,6 +14,7 @@ import {Fraction} from "../coefficients"
14
14
  import {Numeric} from "../numeric"
15
15
 
16
16
  import {ShutingYard, ShutingyardType, type Token} from "piexpression"
17
+ import {MathError, NotImplementedError, ParseError} from "../errors"
17
18
 
18
19
  export class Monom implements IPiMathObject<Monom>, IExpression<Monom>, IAnalyse<Monom>, IAlgebra<Monom> {
19
20
  #coefficient: Fraction
@@ -165,7 +166,7 @@ export class Monom implements IPiMathObject<Monom>, IExpression<Monom>, IAnalyse
165
166
 
166
167
  this.#coefficient.add(mAsMonom.coefficient)
167
168
  } else {
168
- throw new Error('Add monom: ' + this.display + ' is not similar with ' + mAsMonom.display)
169
+ throw new MathError('Add monom: ' + this.display + ' is not similar with ' + mAsMonom.display)
169
170
  }
170
171
  }
171
172
  return this
@@ -650,7 +651,7 @@ export class Monom implements IPiMathObject<Monom>, IExpression<Monom>, IAnalyse
650
651
  */
651
652
  public root = (): this => {
652
653
  // TODO: implement nth-root for monoms
653
- throw new Error('Method not implemented.')
654
+ throw new NotImplementedError('Method not implemented.')
654
655
  }
655
656
 
656
657
  /**
@@ -706,7 +707,7 @@ export class Monom implements IPiMathObject<Monom>, IExpression<Monom>, IAnalyse
706
707
 
707
708
  this.#coefficient.add(mAsMonom.clone().coefficient.opposite())
708
709
  } else {
709
- throw new Error('Subtract: Is not similar: ' + mAsMonom.display)
710
+ throw new MathError('Subtract: Is not similar: ' + mAsMonom.display)
710
711
  }
711
712
  }
712
713
  return this
@@ -890,7 +891,12 @@ export class Monom implements IPiMathObject<Monom>, IExpression<Monom>, IAnalyse
890
891
 
891
892
  #shutingYardToReducedMonom = (inputStr: string): this => {
892
893
  // Get the RPN array of the current expression
893
- const SY: ShutingYard = new ShutingYard().parse(inputStr)
894
+ let SY: ShutingYard
895
+ try {
896
+ SY = new ShutingYard().parse(inputStr)
897
+ } catch (e) {
898
+ throw new ParseError(`Cannot parse "${inputStr}" as a Monom`, {cause: e})
899
+ }
894
900
  const rpn: { token: string, tokenType: ShutingyardType }[] = SY.rpn
895
901
 
896
902
  const stack: Monom[] = []
@@ -1,13 +1,14 @@
1
1
  import type {IExpressionMultiply, IPiMathObject} from "../pimath.interface"
2
+ import {InvalidArgumentError} from "../errors"
2
3
 
3
4
  // TODO: create other operation_** to make things more generic !
4
5
  export function operation_pow<T extends IPiMathObject<T> & IExpressionMultiply<T>>(item: T, value: number): T {
5
6
  if (!Number.isSafeInteger(value)) {
6
- throw new Error('Can only raise item by an integer')
7
+ throw new InvalidArgumentError('Can only raise item by an integer')
7
8
  }
8
9
 
9
10
  if (value < 0) {
10
- throw new Error('Can only raise item by a positive integer')
11
+ throw new InvalidArgumentError('Can only raise item by a positive integer')
11
12
  }
12
13
 
13
14
  if (value === 0) {
@@ -10,6 +10,7 @@ import type {
10
10
  TABLE_OF_SIGNS_VALUES
11
11
  } from "../pimath.interface"
12
12
  import {Fraction} from "../coefficients"
13
+ import {MathError, NotImplementedError, ParseError} from "../errors"
13
14
  import {Factor, FACTOR_DISPLAY} from "./factor"
14
15
  import {Polynom} from "./polynom"
15
16
  import type {Solution} from "../analyze"
@@ -342,7 +343,7 @@ export class PolyFactor implements IPiMathObject<PolyFactor>,
342
343
 
343
344
  if (polynom.isOne()) return this
344
345
 
345
- if (polynom.isZero()) throw new Error("Cannot divide by zero")
346
+ if (polynom.isZero()) throw new MathError("Cannot divide by zero")
346
347
 
347
348
  this.#factors.push(new Factor(polynom, -1))
348
349
  }
@@ -357,8 +358,8 @@ export class PolyFactor implements IPiMathObject<PolyFactor>,
357
358
  // - or the string has something that prevents this => use fromPolynom
358
359
 
359
360
  const [num, ...den] = splitIfOutsideParentheses(value, '/')
360
- if(num==='') throw new Error('Parsing a PolyFactor from a string requires a numerator')
361
- if(den.length>1) throw new Error('Parsing a PolyFactor from a string only allows max one signe "/"')
361
+ if(num==='') throw new ParseError('Parsing a PolyFactor from a string requires a numerator')
362
+ if(den.length>1) throw new ParseError('Parsing a PolyFactor from a string only allows max one signe "/"')
362
363
 
363
364
  if(den.length===0) {
364
365
  this.#factors = Factor.factorsFromString(stripParenthesis(num), true)
@@ -459,7 +460,7 @@ export class PolyFactor implements IPiMathObject<PolyFactor>,
459
460
  }
460
461
 
461
462
  public primitive(): PolyFactor {
462
- throw new Error("Method not implemented.")
463
+ throw new NotImplementedError("Method not implemented.")
463
464
  }
464
465
 
465
466
  public reduce(): this {
@@ -2,6 +2,7 @@
2
2
  * Polynom module contains everything necessary to handle polynoms.*
3
3
  */
4
4
  import {ShutingYard, ShutingyardType, type Token} from "piexpression"
5
+ import {InvalidArgumentError, MathError, ParseError} from "../errors"
5
6
  import type {
6
7
  IAlgebra,
7
8
  IAnalyse,
@@ -212,7 +213,7 @@ export class Polynom implements IPiMathObject<Polynom>,
212
213
  return this.divide(new Polynom(value))
213
214
  }
214
215
 
215
- throw new Error(`Cannot divide by ${value as unknown as string}`)
216
+ throw new MathError(`Cannot divide by ${value as unknown as string}`)
216
217
  }
217
218
 
218
219
  public empty(): this {
@@ -242,7 +243,7 @@ export class Polynom implements IPiMathObject<Polynom>,
242
243
  }
243
244
 
244
245
  if (!this.degree(letter).isNatural() || !P.degree(letter).isNatural()) {
245
- throw new Error('Euclidean division requires integer degrees')
246
+ throw new MathError('Euclidean division requires integer degrees')
246
247
  }
247
248
 
248
249
  // Get at least a letter
@@ -396,7 +397,7 @@ export class Polynom implements IPiMathObject<Polynom>,
396
397
 
397
398
  public getCoefficients(): Fraction[] {
398
399
  if (!this.degree().isNatural()) {
399
- throw new Error('getCoefficients() requires a polynomial with integer degrees')
400
+ throw new MathError('getCoefficients() requires a polynomial with integer degrees')
400
401
  }
401
402
 
402
403
  // Assume there is only one letter.
@@ -462,8 +463,6 @@ export class Polynom implements IPiMathObject<Polynom>,
462
463
  }
463
464
 
464
465
  public isDeveloped(polynomString: string): boolean {
465
- let P: Polynom
466
-
467
466
  // Start by removing the parenthesis after a "power"
468
467
  const pString = polynomString.replaceAll(/\^\(([-0-9/]+)\)/g, '$1')
469
468
 
@@ -473,13 +472,9 @@ export class Polynom implements IPiMathObject<Polynom>,
473
472
  }
474
473
 
475
474
 
476
- // Try to build the polynom
477
- try {
478
- // Build the polynom
479
- P = new Polynom(polynomString)
480
- } catch {
481
- return false
482
- }
475
+ // Build the polynom. A malformed string throws (ParseError) instead of
476
+ // being silently treated as "not developed".
477
+ const P = new Polynom(polynomString)
483
478
 
484
479
  // Both polynom aren't the same (once developed and reduced => they cannot be equivalent)
485
480
  if (!this.isEqual(P)) {
@@ -663,13 +658,13 @@ export class Polynom implements IPiMathObject<Polynom>,
663
658
  try {
664
659
  const k = new Fraction(value)
665
660
  return this.#multiplyByFraction(k)
666
- } catch {
667
- throw new Error('Cannot multiply by this value.')
661
+ } catch (e) {
662
+ throw new MathError('Cannot multiply by this value.', {cause: e})
668
663
  }
669
664
  }
670
665
 
671
666
  // Something went wrong...
672
- throw new Error(`Cannot multiply by this value: ${value as unknown as string}`)
667
+ throw new MathError(`Cannot multiply by this value: ${value as unknown as string}`)
673
668
  }
674
669
 
675
670
  public get numberOfVars(): number {
@@ -801,7 +796,7 @@ export class Polynom implements IPiMathObject<Polynom>,
801
796
 
802
797
  // Add the new monom to the result polynom
803
798
  if (pow.isStrictlyNegative()) {
804
- throw new Error(`Cannot replace variable "${letter}" with negative power in a Polynom`)
799
+ throw new MathError(`Cannot replace variable "${letter}" with negative power in a Polynom`)
805
800
  }
806
801
  resultPolynom.add(P.clone().pow(pow.numerator).multiply(m))
807
802
  }
@@ -817,7 +812,7 @@ export class Polynom implements IPiMathObject<Polynom>,
817
812
  // ------------------------------------------
818
813
 
819
814
  public root(): Polynom {
820
- throw new Error('Cannot take the root from a polynom')
815
+ throw new MathError('Cannot take the root from a polynom')
821
816
  }
822
817
 
823
818
  get roots(): Solution[] {
@@ -836,7 +831,7 @@ export class Polynom implements IPiMathObject<Polynom>,
836
831
  }
837
832
 
838
833
  public sqrt(): Polynom {
839
- throw new Error('Cannot take the square root from a polynom')
834
+ throw new MathError('Cannot take the square root from a polynom')
840
835
  }
841
836
 
842
837
  public subtract(...values: InputAlgebra<Polynom>[]): this {
@@ -1085,7 +1080,7 @@ export class Polynom implements IPiMathObject<Polynom>,
1085
1080
  const letters = inputStr.split('')
1086
1081
 
1087
1082
  if (fractions.length > letters.length + 1) {
1088
- throw new Error(`Too many values: ${letters.length} letters but ${fractions.length} values provided`)
1083
+ throw new InvalidArgumentError(`Too many values: ${letters.length} letters but ${fractions.length} values provided`)
1089
1084
  }
1090
1085
 
1091
1086
  let i = 0
@@ -1127,7 +1122,7 @@ export class Polynom implements IPiMathObject<Polynom>,
1127
1122
  break
1128
1123
 
1129
1124
  case ShutingyardType.CONSTANT:
1130
- throw new Error('Unsupported CONSTANT token in Polynom parser')
1125
+ throw new ParseError('Unsupported CONSTANT token in Polynom parser')
1131
1126
 
1132
1127
  case ShutingyardType.OPERATION:
1133
1128
  if (stack.length >= 2) {
@@ -1136,7 +1131,7 @@ export class Polynom implements IPiMathObject<Polynom>,
1136
1131
 
1137
1132
  // Check if the polynoms are not undefined.
1138
1133
  if (a === undefined || b === undefined) {
1139
- throw new Error('Unexpected undefined operand in Polynom parser stack')
1134
+ throw new ParseError('Unexpected undefined operand in Polynom parser stack')
1140
1135
  }
1141
1136
 
1142
1137
  if (element.token === '+') {
@@ -1147,16 +1142,16 @@ export class Polynom implements IPiMathObject<Polynom>,
1147
1142
  stack.push(a.multiply(b))
1148
1143
  } else if (element.token === '/') {
1149
1144
  if (b.degree().isStrictlyPositive()) {
1150
- throw new Error('Cannot divide a Polynom by another Polynom of degree > 0')
1145
+ throw new MathError('Cannot divide a Polynom by another Polynom of degree > 0')
1151
1146
  } else {
1152
1147
  // a.divide(b.monoms[0].coefficient)
1153
1148
  stack.push(a.divide(b.monoms[0].coefficient))
1154
1149
  }
1155
1150
  } else if (element.token === '^') {
1156
1151
  if (b.degree().isStrictlyPositive()) {
1157
- throw new Error('Cannot elevate a polynom with another polynom !')
1158
- } else if (b.monoms[0].coefficient.isRelative())
1159
- // Integer power
1152
+ throw new MathError('Cannot elevate a polynom with another polynom !')
1153
+ } else if (b.monoms[0].coefficient.isNatural())
1154
+ // Natural (positive) power
1160
1155
  {
1161
1156
  stack.push(a.pow(b.monoms[0].coefficient.value))
1162
1157
  } else {
@@ -1168,7 +1163,7 @@ export class Polynom implements IPiMathObject<Polynom>,
1168
1163
 
1169
1164
  stack.push(a)
1170
1165
  } else {
1171
- throw new Error('Cannot raise a multi-monom Polynom to a fractional power')
1166
+ throw new MathError('Cannot raise a multi-monom Polynom to a fractional power')
1172
1167
  }
1173
1168
  }
1174
1169
  }
@@ -1179,7 +1174,7 @@ export class Polynom implements IPiMathObject<Polynom>,
1179
1174
  stack.push(a.opposite())
1180
1175
  }
1181
1176
  } else {
1182
- throw new Error("Error parsing the polynom")
1177
+ throw new ParseError("Error parsing the polynom")
1183
1178
  }
1184
1179
 
1185
1180
 
@@ -1187,11 +1182,11 @@ export class Polynom implements IPiMathObject<Polynom>,
1187
1182
 
1188
1183
  case ShutingyardType.MONOM:
1189
1184
  // Should never appear.
1190
- throw new Error('Unexpected MONOM token in polynom parser')
1185
+ throw new ParseError('Unexpected MONOM token in polynom parser')
1191
1186
 
1192
1187
  case ShutingyardType.FUNCTION:
1193
1188
  // Should never appear.
1194
- throw new Error(`Unsupported function token "${element.token}" in polynom parser`)
1189
+ throw new ParseError(`Unsupported function token "${element.token}" in polynom parser`)
1195
1190
  }
1196
1191
 
1197
1192
 
@@ -1203,7 +1198,12 @@ export class Polynom implements IPiMathObject<Polynom>,
1203
1198
  */
1204
1199
  #shutingYardToReducedPolynom(inputStr: string): this {
1205
1200
  // Get the RPN array of the current expression
1206
- const SY: ShutingYard = new ShutingYard().parse(inputStr)
1201
+ let SY: ShutingYard
1202
+ try {
1203
+ SY = new ShutingYard().parse(inputStr)
1204
+ } catch (e) {
1205
+ throw new ParseError(`Cannot parse "${inputStr}" as a Polynom`, {cause: e})
1206
+ }
1207
1207
  const rpn: { token: string, tokenType: ShutingyardType }[] = SY.rpn
1208
1208
 
1209
1209
  // New version for reducing shuting yard.