pimath 0.2.13 → 0.2.15

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 (59) hide show
  1. package/dist/pimath.js +856 -1882
  2. package/dist/pimath.js.map +1 -1
  3. package/package.json +2 -2
  4. package/src/algebra/equation.ts +562 -558
  5. package/src/algebra/equationSolver.ts +489 -489
  6. package/src/algebra/factor.ts +396 -392
  7. package/src/algebra/linearSystem.ts +446 -442
  8. package/src/algebra/matrix.ts +515 -511
  9. package/src/algebra/monom.ts +932 -928
  10. package/src/algebra/polyFactor.ts +724 -720
  11. package/src/algebra/polynom.ts +1233 -1229
  12. package/src/coefficients/fraction.ts +907 -748
  13. package/src/coefficients/root.ts +500 -359
  14. package/src/geometry/TupleN.ts +129 -129
  15. package/src/geometry/circle.ts +455 -455
  16. package/src/geometry/line.ts +658 -654
  17. package/src/geometry/point.ts +105 -105
  18. package/src/geometry/sphere3.ts +2 -2
  19. package/src/geometry/triangle.ts +488 -488
  20. package/src/geometry/vector.ts +230 -226
  21. package/src/numeric.ts +136 -51
  22. package/src/pimath.interface.ts +2 -0
  23. package/types/algebra/equation.d.ts +1 -0
  24. package/types/algebra/equation.d.ts.map +1 -1
  25. package/types/algebra/equationSolver.d.ts.map +1 -1
  26. package/types/algebra/factor.d.ts +1 -0
  27. package/types/algebra/factor.d.ts.map +1 -1
  28. package/types/algebra/linearSystem.d.ts +1 -0
  29. package/types/algebra/linearSystem.d.ts.map +1 -1
  30. package/types/algebra/matrix.d.ts +6 -5
  31. package/types/algebra/matrix.d.ts.map +1 -1
  32. package/types/algebra/monom.d.ts +1 -0
  33. package/types/algebra/monom.d.ts.map +1 -1
  34. package/types/algebra/polyFactor.d.ts +1 -0
  35. package/types/algebra/polyFactor.d.ts.map +1 -1
  36. package/types/algebra/polynom.d.ts +1 -0
  37. package/types/algebra/polynom.d.ts.map +1 -1
  38. package/types/coefficients/fraction.d.ts +62 -53
  39. package/types/coefficients/fraction.d.ts.map +1 -1
  40. package/types/coefficients/root.d.ts +3 -0
  41. package/types/coefficients/root.d.ts.map +1 -1
  42. package/types/geometry/TupleN.d.ts +1 -1
  43. package/types/geometry/TupleN.d.ts.map +1 -1
  44. package/types/geometry/circle.d.ts.map +1 -1
  45. package/types/geometry/line.d.ts +1 -0
  46. package/types/geometry/line.d.ts.map +1 -1
  47. package/types/geometry/point.d.ts.map +1 -1
  48. package/types/geometry/sphere3.d.ts +2 -2
  49. package/types/geometry/sphere3.d.ts.map +1 -1
  50. package/types/geometry/triangle.d.ts.map +1 -1
  51. package/types/geometry/vector.d.ts +1 -0
  52. package/types/geometry/vector.d.ts.map +1 -1
  53. package/types/index.d.ts +3 -3
  54. package/types/numeric.d.ts +4 -4
  55. package/types/numeric.d.ts.map +1 -1
  56. package/types/pimath.interface.d.ts +1 -0
  57. package/types/pimath.interface.d.ts.map +1 -1
  58. package/types/primes.data.d.ts +2 -0
  59. package/types/primes.data.d.ts.map +1 -0
@@ -1,512 +1,516 @@
1
- import type {IExpressionMultiply, InputAlgebra, InputValue, IPiMathObject} from "../pimath.interface"
2
- import {Polynom} from "./polynom"
3
- import type {Vector} from "../geometry"
4
- import {operation_pow} from "./operations"
5
- import {DimensionError, IndexError, MathError, NotImplementedError} from "../errors"
6
-
7
- export type IMatrixValues = InputAlgebra<Polynom>[][]
8
-
9
- enum MATRIX_TYPE {
10
- pmatrix,
11
- bmatrix,
12
- Bmatrix,
13
- vmatrix,
14
- Vmatrix
15
- }
16
- export class Matrix implements IPiMathObject<Matrix>,
17
- IExpressionMultiply<Matrix> {
18
- #digits: number | null = null
19
- #matrix_parenthesis: MATRIX_TYPE = MATRIX_TYPE.pmatrix
20
- #values: Polynom[][] = []
21
-
22
- constructor(rowCount?: number, colCount?: number) {
23
- if (rowCount) {
24
- colCount = colCount ?? rowCount
25
- this.fromDimensions(rowCount, colCount)
26
- }
27
-
28
- return this
29
- }
30
-
31
- public parse(values: IMatrixValues): this {
32
- return this.fromValues(values)
33
- }
34
-
35
- public clone(): Matrix {
36
- // Copy the matrix.
37
- const duplicates: IMatrixValues = []
38
-
39
- this.#values.forEach(row => {
40
- const dup_row: Polynom[] = []
41
- row.forEach(value => {
42
- dup_row.push(value.clone())
43
- })
44
-
45
- duplicates.push(dup_row)
46
- })
47
-
48
- return new Matrix().fromValues(duplicates)
49
- }
50
-
51
- get tex(): string {
52
- if (this.#values.length === 0) {
53
- return ""
54
- }
55
-
56
- const wrapper = this.resolveTeXwrapper()
57
-
58
- const output = [
59
- `\\begin{${wrapper}}`,
60
- ...this.rows
61
- .map(row => '\t' + row
62
- .map(p => this.#digits !== null && p.value ? +p.value.toFixed(this.#digits):p.tex)
63
- .join(' & ') + '\\\\'
64
- ),
65
- `\\end{${wrapper}}`
66
- ].join('\n')
67
-
68
- this.#digits = null
69
-
70
- return output
71
- }
72
-
73
- resolveWrapper(): [string, string]{
74
- if(this.#matrix_parenthesis=== MATRIX_TYPE.vmatrix) return ['|', '|']
75
- if(this.#matrix_parenthesis=== MATRIX_TYPE.Vmatrix) return ['||', '||']
76
- if(this.#matrix_parenthesis=== MATRIX_TYPE.bmatrix) return ['[', ']']
77
- if(this.#matrix_parenthesis=== MATRIX_TYPE.Bmatrix) return ['{', '}']
78
-
79
- return ['(', ')']
80
- }
81
-
82
- resolveTeXwrapper(): string {
83
- if(this.#matrix_parenthesis=== MATRIX_TYPE.vmatrix) return 'vmatrix'
84
- if(this.#matrix_parenthesis=== MATRIX_TYPE.Vmatrix) return 'Vmatrix'
85
- if(this.#matrix_parenthesis=== MATRIX_TYPE.bmatrix) return 'bmatrix'
86
- if(this.#matrix_parenthesis=== MATRIX_TYPE.Bmatrix) return 'Bmatrix'
87
-
88
- return 'pmatrix'
89
- }
90
-
91
- get display(): string {
92
- if (this.#values.length === 0) {
93
- return ""
94
- }
95
-
96
- const wrapper = this.resolveWrapper()
97
-
98
- const output = wrapper[0] +
99
- this.map(aij => this.#digits !== null && aij.value ? +aij.value.toFixed(this.#digits): aij.display)
100
- .map(row => `(${row.join(',')})`)
101
- .join(',') +
102
- wrapper[1]
103
-
104
- this.#digits = null
105
-
106
- return output
107
- }
108
-
109
- public add(value: Matrix): this {
110
- if (!this.canBeAdded(value)) {
111
- throw new DimensionError("Cannot add a matrix with different dimensions.")
112
- }
113
- this.forEach((aij, i, j) => {
114
- aij.add(value.values[i][j])
115
- })
116
-
117
- return this
118
- }
119
-
120
- public aij(i: number, j: number) {
121
- if (i < 0 || i > this.dimension.rows || j < 0 || j > this.dimension.cols) {
122
- return null
123
- }
124
-
125
- return this.#values[i][j]
126
- }
127
-
128
- get bmatrix(): this {
129
- this.#matrix_parenthesis = MATRIX_TYPE.bmatrix
130
- return this
131
- }
132
-
133
- get Bmatrix(): this {
134
- this.#matrix_parenthesis = MATRIX_TYPE.Bmatrix
135
- return this
136
- }
137
-
138
- public canBeAdded(matrix: Matrix): boolean {
139
- const {rows, cols} = this.dimension
140
- const {rows: rows2, cols: cols2} = matrix.dimension
141
-
142
- return rows === rows2 && cols === cols2
143
- }
144
-
145
- public canBeInverted(): boolean {
146
- if (!this.isSquare()) {
147
- return false
148
- }
149
-
150
- const determinant = this.determinant()
151
- if (determinant.isZero()) {
152
- return false
153
- }
154
-
155
- return true
156
- }
157
-
158
- public canBeMultiplied(matrix: Matrix): boolean {
159
- return this.dimension.cols === matrix.dimension.rows
160
- }
161
-
162
- public characteristic_polynom(letter?: string): Polynom {
163
- letter ??= 'k'
164
-
165
- return this.clone().subtract(
166
- new Matrix(this.dimension.rows).one().multiply(new Polynom(letter))
167
- ).determinant()
168
- }
169
-
170
- public cofactor(row: number, column: number): Polynom {
171
- // Remove a line.
172
- const coMatrix = this.clone()
173
-
174
- coMatrix.values.splice(row, 1)
175
-
176
- // Remove a column
177
- coMatrix.values.forEach(row => {
178
- row.splice(column, 1)
179
- })
180
-
181
- return coMatrix.determinant().multiply((-1) ** (row + column))
182
- }
183
-
184
- get cols(): Polynom[][] {
185
- // Return the rows of the transposed matrix !
186
- const arr = Array.from({length: this.dimension.cols}, () => {
187
- return Array.from({length: this.dimension.rows}, () => new Polynom())
188
- })
189
-
190
- this.forEach((aij, i, j) => {
191
- arr[j][i] = aij
192
- })
193
-
194
- return arr
195
- }
196
-
197
- public determinant(): Polynom {
198
- if (!this.isSquare()) {
199
- throw new DimensionError('Matrix is not square')
200
- }
201
-
202
- // Use the first line.
203
- // For each value, create the cofactor matrix -> get the determinant
204
- const det = new Polynom()
205
-
206
- // It's a 1x1 matrix
207
- if (this.#values.length === 1) {
208
- return this.#values[0][0].clone()
209
- }
210
-
211
- // It's a matrix greater than 1x1
212
- this.values[0].forEach((aij, column) => {
213
- const C = this.cofactor(0, column)
214
- det.add(aij.clone().multiply(C))
215
- })
216
-
217
- return det
218
- }
219
-
220
- get dimension(): { rows: number, cols: number } {
221
- return {
222
- rows: this.#values.length,
223
- cols: this.#values[0].length,
224
- }
225
- }
226
-
227
- public flat(): Polynom[] {
228
- return this.#values.flat()
229
- }
230
-
231
- public forEach(callback: (aij: Polynom, row: number, column: number) => void): void {
232
- this.#values.forEach((row, i) => {
233
- row.forEach((aij, j) => {
234
- callback(aij, i, j)
235
- })
236
- })
237
- }
238
-
239
- public fromDimensions(rows: number, cols: number): this {
240
- this.#values = Array.from({length: rows}, () => {
241
- return Array.from({length: cols}, () => new Polynom())
242
- }) as unknown as Polynom[][]
243
-
244
- return this
245
- }
246
-
247
- public fromString(value: string): this {
248
- // value = ((a,b),(c,d),(e,f))
249
- if (value.startsWith('((') && value.endsWith("))")) {
250
- return this.fromString(value.substring(1, value.length - 1))
251
- }
252
-
253
- // value = (a,b),(c,d),(e,f)
254
- const arr = value.split('),(')
255
-
256
- this.#values = arr
257
- .map((row, index) => {
258
- // (a,b or c,d or e,f)
259
- if (index === 0) {
260
- return row.substring(1).split(',')
261
- } else if (index === arr.length - 1) {
262
- return row.substring(0, row.length - 1).split(',')
263
- }
264
-
265
- return row.split(',')
266
- })
267
- .map(rowItems =>
268
- rowItems.map(item => new Polynom(item))
269
- )
270
-
271
- return this
272
- }
273
-
274
- public fromValues(values: IMatrixValues): this {
275
- this.#values = []
276
-
277
- // Check dimensions of each rows.
278
- const L = values[0].length
279
- if (values.some(row => row.length !== L)) {
280
- throw new DimensionError("Each line must be the same length")
281
- }
282
-
283
- values.forEach(row => {
284
- const dup_row: Polynom[] = []
285
- row.forEach(value => {
286
- dup_row.push(new Polynom(value))
287
- })
288
-
289
- this.#values.push(dup_row)
290
- })
291
-
292
- return this
293
- }
294
-
295
- public fromVectors(...vectors: Vector[]): this {
296
-
297
- this.#values = []
298
-
299
- // Each vectors must be the same dimension
300
- const L = vectors[0].dimension
301
- if (vectors.some(v => v.dimension !== L)) {
302
- throw new DimensionError("Each vectors must be the same dimension")
303
- }
304
-
305
- this.fromDimensions(vectors[0].dimension, vectors.length)
306
-
307
- vectors.forEach((vector, column) => {
308
- vector.array.forEach((value, row) => {
309
- this.#values[row][column] = new Polynom(value)
310
- })
311
- })
312
-
313
- return this
314
- }
315
-
316
- public inverse(): this {
317
- if (!this.canBeInverted()) {
318
- throw new MathError('The matrix cannot be inverted.')
319
- }
320
-
321
- const cofactors_matrix = new Matrix().fromDimensions(this.dimension.rows, this.dimension.cols)
322
- cofactors_matrix.forEach((_, row, column) => {
323
- cofactors_matrix.setValue(row, column, this.cofactor(row, column))
324
- })
325
-
326
- cofactors_matrix.transpose()
327
-
328
- // Copy the value to "this"
329
- const determinant = this.determinant()
330
- cofactors_matrix.forEach((aij, i, j) => this.setValue(i, j, aij.divide(determinant).reduce()))
331
-
332
- return this
333
- }
334
-
335
- public isEqual(value: Matrix): boolean {
336
- // Two matrix are equals if they are the same dimension and all aij are equals.
337
- if (!this.canBeAdded(value)) {
338
- return false
339
- }
340
-
341
- let aij_are_equals = true
342
- this.forEach((aij, row, column) => {
343
- aij_are_equals &&= aij.isEqual(value.values[row][column])
344
- })
345
-
346
- return aij_are_equals
347
- }
348
-
349
- public isOne(): boolean {
350
- for (let row = 0; row < this.#values.length; row++) {
351
- for (let col = 0; col < this.#values[row].length; col++) {
352
- if (col === row && !this.#values[row][col].isOne()) {
353
- return false
354
- }
355
- if (col !== row && !this.#values[row][col].isZero()) {
356
- return false
357
- }
358
- }
359
- }
360
-
361
- return true
362
- }
363
-
364
- public isSquare(): boolean {
365
- return this.dimension.cols === this.dimension.rows
366
- }
367
-
368
- public isZero(): boolean {
369
- return this.flat().every(v => v.isZero())
370
- }
371
-
372
- public map<T>(callback: (aij: Polynom, row: number, column: number) => T): T[][] {
373
- const {rows, cols} = this.dimension
374
-
375
- const arr = Array.from({length: rows}, () => {
376
- return Array.from({length: cols}, () => undefined as T)
377
- })
378
-
379
- this.#values.forEach((row, i) => {
380
- row.forEach((aij, j) => {
381
- arr[i][j] = callback(aij, i, j)
382
- })
383
- })
384
-
385
- return arr
386
- }
387
-
388
- public multiply(value: InputValue<Polynom> | Matrix): this {
389
- if (value instanceof Matrix) {
390
- if (!this.canBeMultiplied(value)) {
391
- throw new DimensionError(`Cannot multiply a matrix with incompatibles dimensions`)
392
- }
393
-
394
- // Multiply two matrix
395
- const result = new Matrix(this.dimension.rows, value.dimension.cols)
396
- result.forEach((_, i, j) => {
397
- // Multiply this.rows[i] by this.cols[j]
398
- const row = this.rows[i]
399
- const col = value.cols[j]
400
-
401
- const v = new Polynom()
402
-
403
- row.forEach((left, k) => {
404
- v.add(left.clone().multiply(col[k]))
405
- })
406
-
407
- result.setValue(i, j, v)
408
- })
409
-
410
- this.#values = result.values
411
- return this
412
- }
413
-
414
- // Scalar multiplication
415
- this.forEach((aij, i, j) => {
416
- this.setValue(i, j, aij.multiply(value))
417
- })
418
- return this
419
- }
420
-
421
- public one(): this {
422
- this.forEach((aij, row, column) => {
423
- if (row === column) {
424
- aij.one()
425
- } else {
426
- aij.zero()
427
- }
428
- })
429
- return this
430
- }
431
-
432
- public opposite(): this {
433
- this.forEach((aij) => {
434
- aij.opposite()
435
- })
436
- return this
437
- }
438
-
439
- get pmatrix(): this {
440
- this.#matrix_parenthesis = MATRIX_TYPE.pmatrix
441
- return this
442
- }
443
-
444
- get vmatrix(): this {
445
- this.#matrix_parenthesis = MATRIX_TYPE.vmatrix
446
- return this
447
- }
448
-
449
- get Vmatrix(): this {
450
- this.#matrix_parenthesis = MATRIX_TYPE.Vmatrix
451
- return this
452
- }
453
-
454
- public pow(value: number): this {
455
- return operation_pow(this as Matrix, value) as this
456
- }
457
-
458
- public reduce(): Matrix {
459
- throw new NotImplementedError('Not yet implemented')
460
- }
461
-
462
- get rows(): Polynom[][] {
463
- return this.#values
464
- }
465
-
466
- public setValue(row: number, column: number, value: InputAlgebra<Polynom>): this {
467
- const {rows, cols} = this.dimension
468
- if ((row < 0 || row >= rows) ||
469
- column < 0 || column >= cols) {
470
- throw new IndexError(`${row}x${column} is out of range (${rows}x${cols})`)
471
- }
472
-
473
- this.#values[row][column] = new Polynom(value)
474
- return this
475
- }
476
-
477
- public subtract(value: Matrix): this {
478
- if (!this.canBeAdded(value)) {
479
- throw new DimensionError("Cannot subtract a matrix with different dimensions.")
480
- }
481
-
482
- this.forEach((aij, i, j) => {
483
- aij.subtract(value.values[i][j])
484
- })
485
-
486
- return this
487
- }
488
-
489
- toFixed(value: number): this {
490
- this.#digits = value
491
- return this
492
- }
493
-
494
- public transpose(): this {
495
- const temp = this.clone()
496
-
497
- temp.forEach((aij, i, j) => {
498
- this.setValue(j, i, aij.clone())
499
- })
500
-
501
- return this
502
- }
503
-
504
- get values(): Polynom[][] {
505
- return this.#values
506
- }
507
-
508
- public zero(): this {
509
- this.forEach(aij => aij.zero())
510
- return this
511
- }
1
+ import type {IExpressionMultiply, InputAlgebra, InputValue, IPiMathObject} from "../pimath.interface"
2
+ import {Polynom} from "./polynom"
3
+ import type {Vector} from "../geometry"
4
+ import {operation_pow} from "./operations"
5
+ import {DimensionError, IndexError, MathError, NotImplementedError} from "../errors"
6
+
7
+ export type IMatrixValues = InputAlgebra<Polynom>[][]
8
+
9
+ enum MATRIX_TYPE {
10
+ pmatrix,
11
+ bmatrix,
12
+ Bmatrix,
13
+ vmatrix,
14
+ Vmatrix
15
+ }
16
+ export class Matrix implements IPiMathObject<Matrix>,
17
+ IExpressionMultiply<Matrix> {
18
+ #digits: number | null = null
19
+ #matrix_parenthesis: MATRIX_TYPE = MATRIX_TYPE.pmatrix
20
+ #values: Polynom[][] = []
21
+
22
+ constructor(rowCount?: number, colCount?: number) {
23
+ if (rowCount) {
24
+ colCount = colCount ?? rowCount
25
+ this.fromDimensions(rowCount, colCount)
26
+ }
27
+
28
+ return this
29
+ }
30
+
31
+ parse(values: IMatrixValues): this {
32
+ return this.fromValues(values)
33
+ }
34
+
35
+ copy(): this {
36
+ throw new NotImplementedError("copy() is not yet implemented for Matrix")
37
+ }
38
+
39
+ clone(): Matrix {
40
+ // Copy the matrix.
41
+ const duplicates: IMatrixValues = []
42
+
43
+ this.#values.forEach(row => {
44
+ const dup_row: Polynom[] = []
45
+ row.forEach(value => {
46
+ dup_row.push(value.clone())
47
+ })
48
+
49
+ duplicates.push(dup_row)
50
+ })
51
+
52
+ return new Matrix().fromValues(duplicates)
53
+ }
54
+
55
+ get tex(): string {
56
+ if (this.#values.length === 0) {
57
+ return ""
58
+ }
59
+
60
+ const wrapper = this.resolveTeXwrapper()
61
+
62
+ const output = [
63
+ `\\begin{${wrapper}}`,
64
+ ...this.rows
65
+ .map(row => '\t' + row
66
+ .map(p => this.#digits !== null && p.value ? +p.value.toFixed(this.#digits):p.tex)
67
+ .join(' & ') + '\\\\'
68
+ ),
69
+ `\\end{${wrapper}}`
70
+ ].join('\n')
71
+
72
+ this.#digits = null
73
+
74
+ return output
75
+ }
76
+
77
+ resolveWrapper(): [string, string]{
78
+ if(this.#matrix_parenthesis=== MATRIX_TYPE.vmatrix) return ['|', '|']
79
+ if(this.#matrix_parenthesis=== MATRIX_TYPE.Vmatrix) return ['||', '||']
80
+ if(this.#matrix_parenthesis=== MATRIX_TYPE.bmatrix) return ['[', ']']
81
+ if(this.#matrix_parenthesis=== MATRIX_TYPE.Bmatrix) return ['{', '}']
82
+
83
+ return ['(', ')']
84
+ }
85
+
86
+ resolveTeXwrapper(): string {
87
+ if(this.#matrix_parenthesis=== MATRIX_TYPE.vmatrix) return 'vmatrix'
88
+ if(this.#matrix_parenthesis=== MATRIX_TYPE.Vmatrix) return 'Vmatrix'
89
+ if(this.#matrix_parenthesis=== MATRIX_TYPE.bmatrix) return 'bmatrix'
90
+ if(this.#matrix_parenthesis=== MATRIX_TYPE.Bmatrix) return 'Bmatrix'
91
+
92
+ return 'pmatrix'
93
+ }
94
+
95
+ get display(): string {
96
+ if (this.#values.length === 0) {
97
+ return ""
98
+ }
99
+
100
+ const wrapper = this.resolveWrapper()
101
+
102
+ const output = wrapper[0] +
103
+ this.map(aij => this.#digits !== null && aij.value ? +aij.value.toFixed(this.#digits): aij.display)
104
+ .map(row => `(${row.join(',')})`)
105
+ .join(',') +
106
+ wrapper[1]
107
+
108
+ this.#digits = null
109
+
110
+ return output
111
+ }
112
+
113
+ add(value: Matrix): this {
114
+ if (!this.canBeAdded(value)) {
115
+ throw new DimensionError("Cannot add a matrix with different dimensions.")
116
+ }
117
+ this.forEach((aij, i, j) => {
118
+ aij.add(value.values[i][j])
119
+ })
120
+
121
+ return this
122
+ }
123
+
124
+ aij(i: number, j: number) {
125
+ if (i < 0 || i > this.dimension.rows || j < 0 || j > this.dimension.cols) {
126
+ return null
127
+ }
128
+
129
+ return this.#values[i][j]
130
+ }
131
+
132
+ get asBmatrix(): this {
133
+ this.#matrix_parenthesis = MATRIX_TYPE.bmatrix
134
+ return this
135
+ }
136
+
137
+ get asBraceMatrix(): this {
138
+ this.#matrix_parenthesis = MATRIX_TYPE.Bmatrix
139
+ return this
140
+ }
141
+
142
+ canBeAdded(matrix: Matrix): boolean {
143
+ const {rows, cols} = this.dimension
144
+ const {rows: rows2, cols: cols2} = matrix.dimension
145
+
146
+ return rows === rows2 && cols === cols2
147
+ }
148
+
149
+ canBeInverted(): boolean {
150
+ if (!this.isSquare()) {
151
+ return false
152
+ }
153
+
154
+ const determinant = this.determinant()
155
+ if (determinant.isZero()) {
156
+ return false
157
+ }
158
+
159
+ return true
160
+ }
161
+
162
+ canBeMultiplied(matrix: Matrix): boolean {
163
+ return this.dimension.cols === matrix.dimension.rows
164
+ }
165
+
166
+ characteristic_polynom(letter?: string): Polynom {
167
+ letter ??= 'k'
168
+
169
+ return this.clone().subtract(
170
+ new Matrix(this.dimension.rows).one().multiply(new Polynom(letter))
171
+ ).determinant()
172
+ }
173
+
174
+ cofactor(row: number, column: number): Polynom {
175
+ // Remove a line.
176
+ const coMatrix = this.clone()
177
+
178
+ coMatrix.values.splice(row, 1)
179
+
180
+ // Remove a column
181
+ coMatrix.values.forEach(row => {
182
+ row.splice(column, 1)
183
+ })
184
+
185
+ return coMatrix.determinant().multiply((-1) ** (row + column))
186
+ }
187
+
188
+ get cols(): Polynom[][] {
189
+ // Return the rows of the transposed matrix !
190
+ const arr = Array.from({length: this.dimension.cols}, () => {
191
+ return Array.from({length: this.dimension.rows}, () => new Polynom())
192
+ })
193
+
194
+ this.forEach((aij, i, j) => {
195
+ arr[j][i] = aij
196
+ })
197
+
198
+ return arr
199
+ }
200
+
201
+ determinant(): Polynom {
202
+ if (!this.isSquare()) {
203
+ throw new DimensionError('Matrix is not square')
204
+ }
205
+
206
+ // Use the first line.
207
+ // For each value, create the cofactor matrix -> get the determinant
208
+ const det = new Polynom()
209
+
210
+ // It's a 1x1 matrix
211
+ if (this.#values.length === 1) {
212
+ return this.#values[0][0].clone()
213
+ }
214
+
215
+ // It's a matrix greater than 1x1
216
+ this.values[0].forEach((aij, column) => {
217
+ const C = this.cofactor(0, column)
218
+ det.add(aij.clone().multiply(C))
219
+ })
220
+
221
+ return det
222
+ }
223
+
224
+ get dimension(): { rows: number, cols: number } {
225
+ return {
226
+ rows: this.#values.length,
227
+ cols: this.#values[0].length,
228
+ }
229
+ }
230
+
231
+ flat(): Polynom[] {
232
+ return this.#values.flat()
233
+ }
234
+
235
+ forEach(callback: (aij: Polynom, row: number, column: number) => void): void {
236
+ this.#values.forEach((row, i) => {
237
+ row.forEach((aij, j) => {
238
+ callback(aij, i, j)
239
+ })
240
+ })
241
+ }
242
+
243
+ fromDimensions(rows: number, cols: number): this {
244
+ this.#values = Array.from({length: rows}, () => {
245
+ return Array.from({length: cols}, () => new Polynom())
246
+ }) as unknown as Polynom[][]
247
+
248
+ return this
249
+ }
250
+
251
+ fromString(value: string): this {
252
+ // value = ((a,b),(c,d),(e,f))
253
+ if (value.startsWith('((') && value.endsWith("))")) {
254
+ return this.fromString(value.substring(1, value.length - 1))
255
+ }
256
+
257
+ // value = (a,b),(c,d),(e,f)
258
+ const arr = value.split('),(')
259
+
260
+ this.#values = arr
261
+ .map((row, index) => {
262
+ // (a,b or c,d or e,f)
263
+ if (index === 0) {
264
+ return row.substring(1).split(',')
265
+ } else if (index === arr.length - 1) {
266
+ return row.substring(0, row.length - 1).split(',')
267
+ }
268
+
269
+ return row.split(',')
270
+ })
271
+ .map(rowItems =>
272
+ rowItems.map(item => new Polynom(item))
273
+ )
274
+
275
+ return this
276
+ }
277
+
278
+ fromValues(values: IMatrixValues): this {
279
+ this.#values = []
280
+
281
+ // Check dimensions of each rows.
282
+ const L = values[0].length
283
+ if (values.some(row => row.length !== L)) {
284
+ throw new DimensionError("Each line must be the same length")
285
+ }
286
+
287
+ values.forEach(row => {
288
+ const dup_row: Polynom[] = []
289
+ row.forEach(value => {
290
+ dup_row.push(new Polynom(value))
291
+ })
292
+
293
+ this.#values.push(dup_row)
294
+ })
295
+
296
+ return this
297
+ }
298
+
299
+ fromVectors(...vectors: Vector[]): this {
300
+
301
+ this.#values = []
302
+
303
+ // Each vectors must be the same dimension
304
+ const L = vectors[0].dimension
305
+ if (vectors.some(v => v.dimension !== L)) {
306
+ throw new DimensionError("Each vectors must be the same dimension")
307
+ }
308
+
309
+ this.fromDimensions(vectors[0].dimension, vectors.length)
310
+
311
+ vectors.forEach((vector, column) => {
312
+ vector.array.forEach((value, row) => {
313
+ this.#values[row][column] = new Polynom(value)
314
+ })
315
+ })
316
+
317
+ return this
318
+ }
319
+
320
+ inverse(): this {
321
+ if (!this.canBeInverted()) {
322
+ throw new MathError('The matrix cannot be inverted.')
323
+ }
324
+
325
+ const cofactors_matrix = new Matrix().fromDimensions(this.dimension.rows, this.dimension.cols)
326
+ cofactors_matrix.forEach((_, row, column) => {
327
+ cofactors_matrix.setValue(row, column, this.cofactor(row, column))
328
+ })
329
+
330
+ cofactors_matrix.transpose()
331
+
332
+ // Copy the value to "this"
333
+ const determinant = this.determinant()
334
+ cofactors_matrix.forEach((aij, i, j) => this.setValue(i, j, aij.divide(determinant).reduce()))
335
+
336
+ return this
337
+ }
338
+
339
+ isEqual(value: Matrix): boolean {
340
+ // Two matrix are equals if they are the same dimension and all aij are equals.
341
+ if (!this.canBeAdded(value)) {
342
+ return false
343
+ }
344
+
345
+ let aij_are_equals = true
346
+ this.forEach((aij, row, column) => {
347
+ aij_are_equals &&= aij.isEqual(value.values[row][column])
348
+ })
349
+
350
+ return aij_are_equals
351
+ }
352
+
353
+ isOne(): boolean {
354
+ for (let row = 0; row < this.#values.length; row++) {
355
+ for (let col = 0; col < this.#values[row].length; col++) {
356
+ if (col === row && !this.#values[row][col].isOne()) {
357
+ return false
358
+ }
359
+ if (col !== row && !this.#values[row][col].isZero()) {
360
+ return false
361
+ }
362
+ }
363
+ }
364
+
365
+ return true
366
+ }
367
+
368
+ isSquare(): boolean {
369
+ return this.dimension.cols === this.dimension.rows
370
+ }
371
+
372
+ isZero(): boolean {
373
+ return this.flat().every(v => v.isZero())
374
+ }
375
+
376
+ map<T>(callback: (aij: Polynom, row: number, column: number) => T): T[][] {
377
+ const {rows, cols} = this.dimension
378
+
379
+ const arr = Array.from({length: rows}, () => {
380
+ return Array.from({length: cols}, () => undefined as T)
381
+ })
382
+
383
+ this.#values.forEach((row, i) => {
384
+ row.forEach((aij, j) => {
385
+ arr[i][j] = callback(aij, i, j)
386
+ })
387
+ })
388
+
389
+ return arr
390
+ }
391
+
392
+ multiply(value: InputValue<Polynom> | Matrix): this {
393
+ if (value instanceof Matrix) {
394
+ if (!this.canBeMultiplied(value)) {
395
+ throw new DimensionError(`Cannot multiply a matrix with incompatibles dimensions`)
396
+ }
397
+
398
+ // Multiply two matrix
399
+ const result = new Matrix(this.dimension.rows, value.dimension.cols)
400
+ result.forEach((_, i, j) => {
401
+ // Multiply this.rows[i] by this.cols[j]
402
+ const row = this.rows[i]
403
+ const col = value.cols[j]
404
+
405
+ const v = new Polynom()
406
+
407
+ row.forEach((left, k) => {
408
+ v.add(left.clone().multiply(col[k]))
409
+ })
410
+
411
+ result.setValue(i, j, v)
412
+ })
413
+
414
+ this.#values = result.values
415
+ return this
416
+ }
417
+
418
+ // Scalar multiplication
419
+ this.forEach((aij, i, j) => {
420
+ this.setValue(i, j, aij.multiply(value))
421
+ })
422
+ return this
423
+ }
424
+
425
+ one(): this {
426
+ this.forEach((aij, row, column) => {
427
+ if (row === column) {
428
+ aij.one()
429
+ } else {
430
+ aij.zero()
431
+ }
432
+ })
433
+ return this
434
+ }
435
+
436
+ opposite(): this {
437
+ this.forEach((aij) => {
438
+ aij.opposite()
439
+ })
440
+ return this
441
+ }
442
+
443
+ get asPmatrix(): this {
444
+ this.#matrix_parenthesis = MATRIX_TYPE.pmatrix
445
+ return this
446
+ }
447
+
448
+ get asVmatrix(): this {
449
+ this.#matrix_parenthesis = MATRIX_TYPE.vmatrix
450
+ return this
451
+ }
452
+
453
+ get asDoubleVmatrix(): this {
454
+ this.#matrix_parenthesis = MATRIX_TYPE.Vmatrix
455
+ return this
456
+ }
457
+
458
+ pow(value: number): this {
459
+ return operation_pow(this as Matrix, value) as this
460
+ }
461
+
462
+ reduce(): Matrix {
463
+ throw new NotImplementedError('Not yet implemented')
464
+ }
465
+
466
+ get rows(): Polynom[][] {
467
+ return this.#values
468
+ }
469
+
470
+ setValue(row: number, column: number, value: InputAlgebra<Polynom>): this {
471
+ const {rows, cols} = this.dimension
472
+ if ((row < 0 || row >= rows) ||
473
+ column < 0 || column >= cols) {
474
+ throw new IndexError(`${row}x${column} is out of range (${rows}x${cols})`)
475
+ }
476
+
477
+ this.#values[row][column] = new Polynom(value)
478
+ return this
479
+ }
480
+
481
+ subtract(value: Matrix): this {
482
+ if (!this.canBeAdded(value)) {
483
+ throw new DimensionError("Cannot subtract a matrix with different dimensions.")
484
+ }
485
+
486
+ this.forEach((aij, i, j) => {
487
+ aij.subtract(value.values[i][j])
488
+ })
489
+
490
+ return this
491
+ }
492
+
493
+ toFixed(value: number): this {
494
+ this.#digits = value
495
+ return this
496
+ }
497
+
498
+ transpose(): this {
499
+ const temp = this.clone()
500
+
501
+ temp.forEach((aij, i, j) => {
502
+ this.setValue(j, i, aij.clone())
503
+ })
504
+
505
+ return this
506
+ }
507
+
508
+ get values(): Polynom[][] {
509
+ return this.#values
510
+ }
511
+
512
+ zero(): this {
513
+ this.forEach(aij => aij.zero())
514
+ return this
515
+ }
512
516
  }