pimath 0.1.39 → 0.1.40
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.
- package/dist/pimath.js +188 -159
- package/dist/pimath.js.map +1 -1
- package/package.json +4 -2
- package/src/algebra/equation.ts +556 -0
- package/src/algebra/equationSolver.ts +539 -0
- package/src/algebra/factor.ts +339 -0
- package/src/algebra/index.ts +11 -0
- package/src/algebra/linearSystem.ts +388 -0
- package/src/algebra/logicalset.ts +256 -0
- package/src/algebra/matrix.ts +474 -0
- package/src/algebra/monom.ts +1015 -0
- package/src/algebra/operations.ts +24 -0
- package/src/algebra/polyFactor.ts +668 -0
- package/src/algebra/polynom.ts +1394 -0
- package/src/analyze/solution.ts +115 -0
- package/src/analyze/tableOfSigns.ts +30 -0
- package/src/coefficients/fraction.ts +678 -0
- package/src/coefficients/index.ts +4 -0
- package/src/coefficients/nthRoot.ts +149 -0
- package/src/coefficients/root.ts +299 -0
- package/src/geometry/circle.ts +386 -0
- package/src/geometry/geomMath.ts +70 -0
- package/src/geometry/index.ts +10 -0
- package/src/geometry/line.ts +677 -0
- package/src/geometry/line3.ts +206 -0
- package/src/geometry/plane3.ts +170 -0
- package/src/geometry/point.ts +66 -0
- package/src/geometry/sphere3.ts +214 -0
- package/src/geometry/triangle.ts +354 -0
- package/src/geometry/vector.ts +341 -0
- package/src/helpers.ts +35 -0
- package/src/index.ts +60 -0
- package/src/numeric.ts +199 -0
- package/src/pimath.interface.ts +160 -0
- package/src/randomization/algebra/rndEquation.ts +41 -0
- package/src/randomization/algebra/rndMonom.ts +39 -0
- package/src/randomization/algebra/rndPolynom.ts +86 -0
- package/src/randomization/coefficient/rndFraction.ts +38 -0
- package/src/randomization/geometry/rndCircle.ts +27 -0
- package/src/randomization/geometry/rndLine.ts +37 -0
- package/src/randomization/geometry/rndLine3.ts +27 -0
- package/src/randomization/geometry/rndVector.ts +63 -0
- package/src/randomization/random.ts +91 -0
- package/src/randomization/rndHelpers.ts +102 -0
- package/src/randomization/rndTypes.ts +63 -0
- package/types/algebra/equationSolver.d.ts +3 -0
- package/types/algebra/equationSolver.d.ts.map +1 -1
- package/types/algebra/polyFactor.d.ts +5 -0
- package/types/algebra/polyFactor.d.ts.map +1 -1
- package/types/analyze/solution.d.ts +21 -0
- package/types/analyze/solution.d.ts.map +1 -0
- package/types/analyze/tableOfSigns.d.ts +9 -0
- package/types/analyze/tableOfSigns.d.ts.map +1 -0
- package/types/coefficients/root.d.ts +38 -0
- package/types/coefficients/root.d.ts.map +1 -0
- package/types/geometry/point.d.ts +1 -1
- package/types/geometry/point.d.ts.map +1 -1
- package/types/helpers.d.ts +1 -0
- package/types/helpers.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/numeric.d.ts +2 -0
- package/types/numeric.d.ts.map +1 -1
- package/types/pimath.interface.d.ts +26 -26
- package/types/pimath.interface.d.ts.map +1 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// TODO: Remove NthRoot class
|
|
2
|
+
/**
|
|
3
|
+
* NthRoot is something like "a+b\sqrt{3}
|
|
4
|
+
*/
|
|
5
|
+
export class NthRoot {
|
|
6
|
+
#radical: number
|
|
7
|
+
#nth: number
|
|
8
|
+
#coefficient: number
|
|
9
|
+
#isValid: boolean
|
|
10
|
+
|
|
11
|
+
constructor(...values: number[]) {
|
|
12
|
+
this.#radical = 1
|
|
13
|
+
this.#coefficient = 1
|
|
14
|
+
this.#nth = 2
|
|
15
|
+
this.#isValid = true
|
|
16
|
+
|
|
17
|
+
if (values.length > 0) {
|
|
18
|
+
this.parse(values[0], values[1], values[2])
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ------------------------------------------
|
|
23
|
+
// Getter and setter
|
|
24
|
+
// ------------------------------------------
|
|
25
|
+
get radical(): number {
|
|
26
|
+
return this.#radical
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
set radical(value: number) {
|
|
30
|
+
this.#radical = value
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get nth(): number {
|
|
34
|
+
return this.#nth
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
set nth(value: number) {
|
|
38
|
+
if (Number.isSafeInteger(value) && value >= 2) {
|
|
39
|
+
this.#nth = value
|
|
40
|
+
} else {
|
|
41
|
+
// Error setting the nth root.
|
|
42
|
+
console.log('Error setting the nth root')
|
|
43
|
+
this.#nth = 2
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get coefficient(): number {
|
|
48
|
+
return this.#coefficient
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
set coefficient(value: number) {
|
|
52
|
+
this.#coefficient = value
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
get tex(): string {
|
|
56
|
+
let C: string
|
|
57
|
+
|
|
58
|
+
if (this.#coefficient === 1) {
|
|
59
|
+
C = ''
|
|
60
|
+
} else if (this.#coefficient === -1) {
|
|
61
|
+
C = '-'
|
|
62
|
+
} else {
|
|
63
|
+
C = this.#coefficient.toString()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (this.#radical === 1) {
|
|
67
|
+
return `${this.#coefficient}`
|
|
68
|
+
} else {
|
|
69
|
+
if (this.#nth === 2) {
|
|
70
|
+
return `${C}\\sqrt{${this.#radical}}`
|
|
71
|
+
} else {
|
|
72
|
+
return `${C}\\sqrt[${this.#nth}]{${this.#radical}}`
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get display(): string {
|
|
78
|
+
let C: string
|
|
79
|
+
|
|
80
|
+
if (this.#coefficient === 1) {
|
|
81
|
+
C = ''
|
|
82
|
+
} else if (this.#coefficient === -1) {
|
|
83
|
+
C = '-'
|
|
84
|
+
} else {
|
|
85
|
+
C = this.#coefficient.toString()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (this.#radical === 1) {
|
|
89
|
+
return `${this.#coefficient}`
|
|
90
|
+
} else {
|
|
91
|
+
if (this.#nth === 2) {
|
|
92
|
+
return `${C}sqrt{${this.#radical}}`
|
|
93
|
+
} else {
|
|
94
|
+
return `${C}root(${this.#nth}){${this.#radical}}`
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get value(): number {
|
|
100
|
+
return this.#coefficient * Math.pow(this.#radical, 1 / this.#nth)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ------------------------------------------
|
|
104
|
+
// Creation / parsing functions
|
|
105
|
+
// ------------------------------------------
|
|
106
|
+
parse = (radical: number, nthroot?: number, coefficient?: number): this => {
|
|
107
|
+
this.#coefficient = coefficient ?? 1
|
|
108
|
+
this.#nth = nthroot ?? 2
|
|
109
|
+
this.#radical = radical
|
|
110
|
+
|
|
111
|
+
if (this.#nth % 2 === 0 && this.#radical < 0) {
|
|
112
|
+
this.#isValid = false
|
|
113
|
+
}
|
|
114
|
+
return this
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ------------------------------------------
|
|
118
|
+
// Mathematical operations
|
|
119
|
+
// ------------------------------------------
|
|
120
|
+
reduce = (): this => {
|
|
121
|
+
// Max value to test.
|
|
122
|
+
let V = Math.floor(Math.pow(this.#radical, 1 / this.#nth))
|
|
123
|
+
while (V > 1) {
|
|
124
|
+
if (this.#radical % Math.pow(V, this.#nth) === 0) {
|
|
125
|
+
// It's dividable by V^n
|
|
126
|
+
this.#coefficient *= V
|
|
127
|
+
this.#radical = this.#radical / Math.pow(V, this.#nth)
|
|
128
|
+
|
|
129
|
+
// Redifine the new testing value (this is optimization)
|
|
130
|
+
V = Math.floor(Math.pow(this.#radical, 1 / this.#nth))
|
|
131
|
+
continue
|
|
132
|
+
}
|
|
133
|
+
V--
|
|
134
|
+
}
|
|
135
|
+
return this
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
multiply = (N: NthRoot): this => {
|
|
139
|
+
this.#radical *= N.radical
|
|
140
|
+
return this.reduce()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ------------------------------------------
|
|
144
|
+
// Help functions
|
|
145
|
+
// ------------------------------------------
|
|
146
|
+
hasRadical = (): boolean => {
|
|
147
|
+
return !(this.#radical === 1 || this.#radical === 0 || !this.#isValid)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import {Fraction} from "./fraction"
|
|
2
|
+
import type {IExpression, InputValue, IPiMathObject} from "../pimath.interface"
|
|
3
|
+
import {stripParenthesis} from "../helpers"
|
|
4
|
+
import {Numeric} from "../numeric"
|
|
5
|
+
|
|
6
|
+
export class Root implements IPiMathObject<Root>, IExpression<Root> {
|
|
7
|
+
#factor: Fraction
|
|
8
|
+
#index: number
|
|
9
|
+
#radical: Fraction
|
|
10
|
+
|
|
11
|
+
constructor(value?: InputValue<Root | Fraction>) {
|
|
12
|
+
this.#index = 2
|
|
13
|
+
this.#factor = new Fraction().one()
|
|
14
|
+
this.#radical = new Fraction().zero()
|
|
15
|
+
|
|
16
|
+
if (value) {
|
|
17
|
+
this.parse(value)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
return this
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
parse(value: InputValue<Root | Fraction>): this {
|
|
25
|
+
// should be able to parse "display" roots.
|
|
26
|
+
// sqrt12 or sqrt(12) or sqrt(12/5) => [2, 12 or 12/5, 1]
|
|
27
|
+
// root(n)10 or root(n)(10) or root(n)(10/3) => [n, 10 or 10/3, 1]
|
|
28
|
+
// 7sqrt12 or 7sqrt(12) or 7sqrt(12/5) => [2, 12 or 12/5, 7]
|
|
29
|
+
// 7root(n)10 or 7root(n)(10) or 7root(n)(10/3) => [n, 10 or 10/3, 7]
|
|
30
|
+
|
|
31
|
+
if (value instanceof Root) {
|
|
32
|
+
this.index = value.index
|
|
33
|
+
this.radical = value.radical.clone()
|
|
34
|
+
this.factor = value.factor.clone()
|
|
35
|
+
|
|
36
|
+
return this
|
|
37
|
+
}
|
|
38
|
+
if (value instanceof Fraction) {
|
|
39
|
+
this.index = 2
|
|
40
|
+
this.factor = value.clone()
|
|
41
|
+
this.radical.one()
|
|
42
|
+
|
|
43
|
+
return this
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (typeof value === "string") {
|
|
47
|
+
if (value.includes('sqrt')) {
|
|
48
|
+
return this.#parse_sqrt(value)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (value.includes('root')) {
|
|
52
|
+
return this.#parse_root(value)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.index = 2
|
|
57
|
+
this.factor = new Fraction(value)
|
|
58
|
+
this.radical.one()
|
|
59
|
+
|
|
60
|
+
return this
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
clone(): Root {
|
|
64
|
+
return new Root().from(this.index, this.radical, this.factor)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get tex(): string {
|
|
68
|
+
const output =
|
|
69
|
+
this.factor.isOne()
|
|
70
|
+
? ''
|
|
71
|
+
: this.factor.isNegative()
|
|
72
|
+
? '-'
|
|
73
|
+
: this.factor.tex
|
|
74
|
+
|
|
75
|
+
if (this.index === 1) {
|
|
76
|
+
|
|
77
|
+
return output
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (this.index === 2) {
|
|
81
|
+
|
|
82
|
+
return output
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return output
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get display(): string {
|
|
89
|
+
return this.factor.display
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
add(value: InputValue<Root>): this {
|
|
93
|
+
const rt = new Root(value)
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
this.index !== rt.index &&
|
|
97
|
+
!this.radical.isEqual(rt.radical)
|
|
98
|
+
) {
|
|
99
|
+
throw new Error("Add can only be done with two same index and radical")
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.factor.add(rt.factor)
|
|
103
|
+
|
|
104
|
+
return this
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
divide(value: InputValue<Root>): this {
|
|
108
|
+
return this.multiply(new Root(value).inverse())
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
get factor(): Fraction {
|
|
112
|
+
return this.#factor
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
set factor(value: Fraction) {
|
|
116
|
+
this.#factor = value
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
from(index: number, radical: InputValue<Fraction>, factor?: InputValue<Fraction>): this {
|
|
120
|
+
// set the index
|
|
121
|
+
this.index = index
|
|
122
|
+
|
|
123
|
+
// set the racial
|
|
124
|
+
this.radical = new Fraction(radical)
|
|
125
|
+
|
|
126
|
+
// set the factor if any
|
|
127
|
+
this.factor = factor ? new Fraction(factor) : new Fraction().one()
|
|
128
|
+
|
|
129
|
+
return this
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* convert to root(index)(radical), without factor
|
|
134
|
+
*/
|
|
135
|
+
group(): this {
|
|
136
|
+
|
|
137
|
+
this.radical.multiply(this.factor.pow(this.index))
|
|
138
|
+
this.factor.one()
|
|
139
|
+
|
|
140
|
+
return this
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
get index(): number {
|
|
144
|
+
return this.#index
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
set index(value: number) {
|
|
148
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
149
|
+
throw new Error("Index must be a strictly positive integer.")
|
|
150
|
+
}
|
|
151
|
+
this.#index = value
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
get indexAsPow(): Fraction {
|
|
155
|
+
return new Fraction(this.index).inverse()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
inverse(): this {
|
|
159
|
+
this.factor.inverse()
|
|
160
|
+
this.radical.inverse()
|
|
161
|
+
return this
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
isEqual(root: Root): boolean {
|
|
165
|
+
return this.value === root.value
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
isOne(): boolean {
|
|
169
|
+
return this.factor.isOne() && this.radical.isOne()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
isZero(): boolean {
|
|
173
|
+
return this.factor.isZero() || this.radical.isZero()
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
multiply(value: InputValue<Root>): this {
|
|
177
|
+
const rt = new Root(value)
|
|
178
|
+
|
|
179
|
+
this.factor.multiply(rt.factor)
|
|
180
|
+
|
|
181
|
+
if (this.index === rt.index) {
|
|
182
|
+
this.radical.multiply(rt.radical)
|
|
183
|
+
return this
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (this.radical.isEqual(rt.radical)) {
|
|
187
|
+
const F = this.indexAsPow.add(rt.indexAsPow).reduce()
|
|
188
|
+
this.index = F.denominator
|
|
189
|
+
this.radical = this.radical.pow(F.numerator)
|
|
190
|
+
return this
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
throw new Error('Multiply can only be done if radical or index as equals.')
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
one(): this {
|
|
197
|
+
this.radical.one()
|
|
198
|
+
this.factor.one()
|
|
199
|
+
|
|
200
|
+
return this
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
opposite(): this {
|
|
204
|
+
this.factor.opposite()
|
|
205
|
+
return this
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
pow(value: number): this {
|
|
209
|
+
this.factor.pow(value)
|
|
210
|
+
|
|
211
|
+
const g = Numeric.gcd(this.index, value)
|
|
212
|
+
this.index = this.index / g
|
|
213
|
+
this.radical.pow(value / g)
|
|
214
|
+
|
|
215
|
+
return this
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
get radical(): Fraction {
|
|
219
|
+
return this.#radical
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
set radical(value: Fraction) {
|
|
223
|
+
this.#radical = value
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
reduce(): this {
|
|
227
|
+
// 1. extract roots
|
|
228
|
+
// 2. avoid roots at denominator.
|
|
229
|
+
|
|
230
|
+
// Remove the roots at denominator
|
|
231
|
+
if (this.radical.isRational()) {
|
|
232
|
+
const den = this.radical.denominator
|
|
233
|
+
this.radical.denominator = 1
|
|
234
|
+
this.radical.numerator *= den
|
|
235
|
+
|
|
236
|
+
this.factor.divide(den)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Extract the greatest root from.
|
|
240
|
+
const greatest = Numeric.greatestPower(this.radical.value, this.index)
|
|
241
|
+
this.factor = this.factor.multiply(Math.pow(greatest, 1 / this.index))
|
|
242
|
+
this.radical = this.radical.divide(greatest)
|
|
243
|
+
|
|
244
|
+
return this
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
root(value: number): this {
|
|
248
|
+
this.group()
|
|
249
|
+
this.index = this.index * value
|
|
250
|
+
return this
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
sqrt(): this {
|
|
254
|
+
return this.root(2)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
subtract(value: InputValue<Root>): this {
|
|
258
|
+
const rt = new Root(value)
|
|
259
|
+
|
|
260
|
+
return this.add(rt.opposite())
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
public get value(): number {
|
|
264
|
+
return Numeric.numberCorrection(this.factor.value * Math.pow(this.radical.value, 1 / this.index))
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
zero(): this {
|
|
268
|
+
this.radical.zero()
|
|
269
|
+
this.factor.zero()
|
|
270
|
+
return this
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
#parse_root(value: string): this {
|
|
274
|
+
// value = a root(n)b or a root(n)(b)
|
|
275
|
+
const [factor, index_radical] = value.split('root')
|
|
276
|
+
const [index, radical] = index_radical.split(')')
|
|
277
|
+
|
|
278
|
+
this.index = +stripParenthesis(index)
|
|
279
|
+
|
|
280
|
+
this.radical = new Fraction(stripParenthesis(radical))
|
|
281
|
+
|
|
282
|
+
this.factor = factor === '' ? new Fraction().one() : new Fraction(factor)
|
|
283
|
+
|
|
284
|
+
return this
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
#parse_sqrt(value: string): this {
|
|
288
|
+
// value = asqrtb
|
|
289
|
+
const [factor, radical] = value.split('sqrt')
|
|
290
|
+
|
|
291
|
+
this.index = 2
|
|
292
|
+
|
|
293
|
+
this.radical = new Fraction(stripParenthesis(radical))
|
|
294
|
+
|
|
295
|
+
this.factor = factor === '' ? new Fraction().one() : new Fraction(factor)
|
|
296
|
+
|
|
297
|
+
return this
|
|
298
|
+
}
|
|
299
|
+
}
|