pimath 0.2.14 → 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.
- package/dist/pimath.js +850 -1879
- package/dist/pimath.js.map +1 -1
- package/package.json +1 -1
- package/src/algebra/equation.ts +562 -558
- package/src/algebra/equationSolver.ts +489 -489
- package/src/algebra/factor.ts +396 -392
- package/src/algebra/linearSystem.ts +446 -442
- package/src/algebra/matrix.ts +515 -511
- package/src/algebra/monom.ts +932 -928
- package/src/algebra/polyFactor.ts +724 -720
- package/src/algebra/polynom.ts +1233 -1229
- package/src/coefficients/fraction.ts +907 -748
- package/src/coefficients/root.ts +500 -359
- package/src/geometry/TupleN.ts +129 -129
- package/src/geometry/circle.ts +455 -455
- package/src/geometry/line.ts +658 -654
- package/src/geometry/point.ts +105 -105
- package/src/geometry/sphere3.ts +2 -2
- package/src/geometry/triangle.ts +488 -488
- package/src/geometry/vector.ts +230 -226
- package/src/numeric.ts +136 -51
- package/src/pimath.interface.ts +2 -0
- package/types/algebra/equation.d.ts +1 -0
- package/types/algebra/equation.d.ts.map +1 -1
- package/types/algebra/equationSolver.d.ts.map +1 -1
- package/types/algebra/factor.d.ts +1 -0
- package/types/algebra/factor.d.ts.map +1 -1
- package/types/algebra/linearSystem.d.ts +1 -0
- package/types/algebra/linearSystem.d.ts.map +1 -1
- package/types/algebra/matrix.d.ts +6 -5
- package/types/algebra/matrix.d.ts.map +1 -1
- package/types/algebra/monom.d.ts +1 -0
- package/types/algebra/monom.d.ts.map +1 -1
- package/types/algebra/polyFactor.d.ts +1 -0
- package/types/algebra/polyFactor.d.ts.map +1 -1
- package/types/algebra/polynom.d.ts +1 -0
- package/types/algebra/polynom.d.ts.map +1 -1
- package/types/coefficients/fraction.d.ts +62 -53
- package/types/coefficients/fraction.d.ts.map +1 -1
- package/types/coefficients/root.d.ts +3 -0
- package/types/coefficients/root.d.ts.map +1 -1
- package/types/geometry/TupleN.d.ts +1 -1
- package/types/geometry/TupleN.d.ts.map +1 -1
- package/types/geometry/circle.d.ts.map +1 -1
- package/types/geometry/line.d.ts +1 -0
- package/types/geometry/line.d.ts.map +1 -1
- package/types/geometry/point.d.ts.map +1 -1
- package/types/geometry/sphere3.d.ts +2 -2
- package/types/geometry/sphere3.d.ts.map +1 -1
- package/types/geometry/triangle.d.ts.map +1 -1
- package/types/geometry/vector.d.ts +1 -0
- package/types/geometry/vector.d.ts.map +1 -1
- package/types/index.d.ts +3 -3
- package/types/numeric.d.ts +4 -4
- package/types/numeric.d.ts.map +1 -1
- package/types/pimath.interface.d.ts +1 -0
- package/types/pimath.interface.d.ts.map +1 -1
- package/types/primes.data.d.ts +2 -0
- package/types/primes.data.d.ts.map +1 -0
package/src/geometry/vector.ts
CHANGED
|
@@ -1,226 +1,230 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Vector2D module contains everything necessary to handle 2d vectors.
|
|
3
|
-
* @module Vector
|
|
4
|
-
*/
|
|
5
|
-
import type {InputValue, IPiMathObject} from "../pimath.interface"
|
|
6
|
-
import {Fraction} from "../coefficients"
|
|
7
|
-
import {Numeric} from "../numeric"
|
|
8
|
-
import {areVectorsColinears, areVectorsEquals, dotProduct} from "./geomMath"
|
|
9
|
-
import {DimensionError, InvalidArgumentError} from "../errors"
|
|
10
|
-
import {TupleN} from "./TupleN"
|
|
11
|
-
import {type Point} from "./point"
|
|
12
|
-
|
|
13
|
-
export class Vector extends TupleN implements IPiMathObject<Vector> {
|
|
14
|
-
constructor(...values: (Vector | Point)[] | InputValue<Fraction>[]) {
|
|
15
|
-
super()
|
|
16
|
-
|
|
17
|
-
if (values.length > 0) {
|
|
18
|
-
this.parse(...values)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return this
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// ------------------------------------------
|
|
25
|
-
// Getter and setter
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (values.length === 0) {
|
|
29
|
-
throw new InvalidArgumentError(`Invalid value`)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (values.length === 1) {
|
|
33
|
-
if (values[0] instanceof TupleN) {
|
|
34
|
-
this.array = values[0].
|
|
35
|
-
return this
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (typeof values[0] === 'string') {
|
|
39
|
-
return this.fromString(values[0])
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
throw new InvalidArgumentError(`Invalid value`)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Two values are given
|
|
46
|
-
if (values.length === 2) {
|
|
47
|
-
const [A, B] = values
|
|
48
|
-
|
|
49
|
-
// The two values are vectors
|
|
50
|
-
if (A instanceof TupleN && B instanceof TupleN) {
|
|
51
|
-
if (A.dimension !== B.dimension) {
|
|
52
|
-
throw new DimensionError('Vectors must have the same dimension')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
this.array = B.array.map((x, index) => x.clone().subtract(A.array[index]))
|
|
56
|
-
return this
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Two ore more values as number, string, fraction...
|
|
61
|
-
this.array = values.map(x => new Fraction(x as InputValue<Fraction>))
|
|
62
|
-
return this
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return new Vector(...this.
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
get
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return `((${
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
static
|
|
82
|
-
return
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return this
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return this.array.every(
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return this.array.every(x => x.isZero())
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
get
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
this
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
this
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return this
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
this.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Vector2D module contains everything necessary to handle 2d vectors.
|
|
3
|
+
* @module Vector
|
|
4
|
+
*/
|
|
5
|
+
import type {InputValue, IPiMathObject} from "../pimath.interface"
|
|
6
|
+
import {Fraction} from "../coefficients"
|
|
7
|
+
import {Numeric} from "../numeric"
|
|
8
|
+
import {areVectorsColinears, areVectorsEquals, dotProduct} from "./geomMath"
|
|
9
|
+
import {DimensionError, InvalidArgumentError, NotImplementedError} from "../errors"
|
|
10
|
+
import {TupleN} from "./TupleN"
|
|
11
|
+
import {type Point} from "./point"
|
|
12
|
+
|
|
13
|
+
export class Vector extends TupleN implements IPiMathObject<Vector> {
|
|
14
|
+
constructor(...values: (Vector | Point)[] | InputValue<Fraction>[]) {
|
|
15
|
+
super()
|
|
16
|
+
|
|
17
|
+
if (values.length > 0) {
|
|
18
|
+
this.parse(...values)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return this
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// ------------------------------------------
|
|
25
|
+
// Getter and setter
|
|
26
|
+
|
|
27
|
+
parse(...values: (Vector | Point)[] | InputValue<Fraction>[]): this {
|
|
28
|
+
if (values.length === 0) {
|
|
29
|
+
throw new InvalidArgumentError(`Invalid value`)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (values.length === 1) {
|
|
33
|
+
if (values[0] instanceof TupleN) {
|
|
34
|
+
this.array = values[0].cloneCoordinates()
|
|
35
|
+
return this
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (typeof values[0] === 'string') {
|
|
39
|
+
return this.fromString(values[0])
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
throw new InvalidArgumentError(`Invalid value`)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Two values are given
|
|
46
|
+
if (values.length === 2) {
|
|
47
|
+
const [A, B] = values
|
|
48
|
+
|
|
49
|
+
// The two values are vectors
|
|
50
|
+
if (A instanceof TupleN && B instanceof TupleN) {
|
|
51
|
+
if (A.dimension !== B.dimension) {
|
|
52
|
+
throw new DimensionError('Vectors must have the same dimension')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.array = B.array.map((x, index) => x.clone().subtract(A.array[index]))
|
|
56
|
+
return this
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Two ore more values as number, string, fraction...
|
|
61
|
+
this.array = values.map(x => new Fraction(x as InputValue<Fraction>))
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
clone(): Vector {
|
|
66
|
+
return new Vector(...this.cloneCoordinates())
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
copy(): this {
|
|
70
|
+
throw new NotImplementedError("copy() is not yet implemented for Vector")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get tex(): string {
|
|
74
|
+
return `\\begin{pmatrix} ${this.array.map(x => x.tex).join(' \\\\ ')} \\end{pmatrix}`
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get display(): string {
|
|
78
|
+
return `((${this.array.map(x => x.display).join(',')}))`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static asDisplay(...values: string[]): string {
|
|
82
|
+
return `((${values.join(',')}))`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static asTex(...values: string[]): string {
|
|
86
|
+
return `\\begin{pmatrix} ${values.join(' \\\\ ')} \\end{pmatrix}`
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
add = (V: Vector): this => {
|
|
90
|
+
this.array.forEach((x, index) => x.add(V.array[index]))
|
|
91
|
+
return this
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
angle = (V: Vector, sharp?: boolean, radian?: boolean): number => {
|
|
95
|
+
|
|
96
|
+
let scalar = this.dot(V).value
|
|
97
|
+
if (sharp) {
|
|
98
|
+
scalar = Math.abs(scalar)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const toDegree = radian ? 1 : 180 / Math.PI
|
|
102
|
+
|
|
103
|
+
return toDegree * Math.acos(scalar / (this.norm * V.norm))
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
cross(value: Vector): Vector {
|
|
107
|
+
if (this.dimension !== 3 || value.dimension !== 3) {
|
|
108
|
+
throw new DimensionError('Cross product can only be determined in 3D')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return new Vector(
|
|
112
|
+
this.y.clone().multiply(value.z).subtract(this.z.clone().multiply(value.y)),
|
|
113
|
+
this.z.clone().multiply(value.x).subtract(this.x.clone().multiply(value.z)),
|
|
114
|
+
this.x.clone().multiply(value.y).subtract(this.y.clone().multiply(value.x))
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ------------------------------------------
|
|
119
|
+
// Creation / parsing functions
|
|
120
|
+
|
|
121
|
+
divideByScalar = (k: InputValue<Fraction>): this => {
|
|
122
|
+
return this.multiplyByScalar(new Fraction(k).inverse())
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
dot = (V: Vector |Point): Fraction => {
|
|
126
|
+
return dotProduct(this, V)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
override fromString(value: string): this {
|
|
130
|
+
if (value.startsWith('((') && value.endsWith('))')) {
|
|
131
|
+
return super.fromString(value.slice(1, -1))
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return super.fromString(value)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
isColinearTo = (v: Vector): boolean => {
|
|
138
|
+
return areVectorsColinears(this, v)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
isEqual = (v: Vector): boolean => {
|
|
142
|
+
return areVectorsEquals(this, v)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
isNormalTo = (v: Vector): boolean => {
|
|
146
|
+
return this.dot(v).isZero()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ------------------------------------------
|
|
150
|
+
get isNull(): boolean {
|
|
151
|
+
return this.array.every(x => x.isZero())
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
isOne(): boolean {
|
|
155
|
+
return this.array.every((x, index) => index === 0 ? x.isOne() : x.isZero())
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
isZero(): boolean {
|
|
159
|
+
return this.array.every(x => x.isZero())
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
multiplyByScalar = (k: InputValue<Fraction>): this => {
|
|
163
|
+
const scalar = new Fraction(k)
|
|
164
|
+
this.array.forEach(x => x.multiply(scalar))
|
|
165
|
+
return this
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
get norm(): number {
|
|
169
|
+
return Math.sqrt(this.normSquare.value)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
get normSquare(): Fraction {
|
|
173
|
+
// Get the norm square of the vector
|
|
174
|
+
return this.array.reduce((acc, x) => acc.add(x.clone().pow(2)), new Fraction(0))
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
normal = (): this => {
|
|
178
|
+
if (this.dimension >= 3) {
|
|
179
|
+
throw new DimensionError('Normal vector can only be determined in 2D')
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const x = this.x.clone().opposite()
|
|
183
|
+
const y = this.y.clone()
|
|
184
|
+
|
|
185
|
+
this.array[0] = y
|
|
186
|
+
this.array[1] = x
|
|
187
|
+
return this
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
one = (): this => {
|
|
191
|
+
this.zero()
|
|
192
|
+
this.x.one()
|
|
193
|
+
return this
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
opposite = (): this => {
|
|
197
|
+
this.array.forEach(x => x.opposite())
|
|
198
|
+
return this
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
simplify = (): this => {
|
|
202
|
+
const lcm = Numeric.lcm(...this.array.map(x => x.denominator))
|
|
203
|
+
const gcd = Numeric.gcd(...this.array.map(x => x.numerator))
|
|
204
|
+
|
|
205
|
+
this.multiplyByScalar(new Fraction(lcm, gcd))
|
|
206
|
+
|
|
207
|
+
if(this.x.isNegative()) this.opposite()
|
|
208
|
+
|
|
209
|
+
return this
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
subtract = (V: Vector): this => {
|
|
213
|
+
return this.add(V.clone().opposite())
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
translate(...values: Fraction[]): this {
|
|
217
|
+
this.array.forEach((x, index) => x.add(values[index]))
|
|
218
|
+
return this
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
unit = (): this => {
|
|
222
|
+
const norm = this.norm
|
|
223
|
+
if (norm === 0) {
|
|
224
|
+
return this
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return this.divideByScalar(norm)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
}
|