@pawells/math-extended 1.0.1

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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +319 -0
  3. package/build/angles.d.ts +31 -0
  4. package/build/angles.d.ts.map +1 -0
  5. package/build/angles.js +85 -0
  6. package/build/angles.js.map +1 -0
  7. package/build/angles.spec.d.ts +2 -0
  8. package/build/angles.spec.d.ts.map +1 -0
  9. package/build/angles.spec.js +147 -0
  10. package/build/angles.spec.js.map +1 -0
  11. package/build/clamp.d.ts +17 -0
  12. package/build/clamp.d.ts.map +1 -0
  13. package/build/clamp.js +19 -0
  14. package/build/clamp.js.map +1 -0
  15. package/build/clamp.spec.d.ts +2 -0
  16. package/build/clamp.spec.d.ts.map +1 -0
  17. package/build/clamp.spec.js +19 -0
  18. package/build/clamp.spec.js.map +1 -0
  19. package/build/documentation-validation.spec.d.ts +11 -0
  20. package/build/documentation-validation.spec.d.ts.map +1 -0
  21. package/build/documentation-validation.spec.js +401 -0
  22. package/build/documentation-validation.spec.js.map +1 -0
  23. package/build/index.d.ts +8 -0
  24. package/build/index.d.ts.map +1 -0
  25. package/build/index.js +8 -0
  26. package/build/index.js.map +1 -0
  27. package/build/interpolation.d.ts +175 -0
  28. package/build/interpolation.d.ts.map +1 -0
  29. package/build/interpolation.js +369 -0
  30. package/build/interpolation.js.map +1 -0
  31. package/build/interpolation.spec.d.ts +2 -0
  32. package/build/interpolation.spec.d.ts.map +1 -0
  33. package/build/interpolation.spec.js +480 -0
  34. package/build/interpolation.spec.js.map +1 -0
  35. package/build/matrices/arithmetic.d.ts +411 -0
  36. package/build/matrices/arithmetic.d.ts.map +1 -0
  37. package/build/matrices/arithmetic.js +954 -0
  38. package/build/matrices/arithmetic.js.map +1 -0
  39. package/build/matrices/arithmetic.spec.d.ts +2 -0
  40. package/build/matrices/arithmetic.spec.d.ts.map +1 -0
  41. package/build/matrices/arithmetic.spec.js +915 -0
  42. package/build/matrices/arithmetic.spec.js.map +1 -0
  43. package/build/matrices/asserts.d.ts +306 -0
  44. package/build/matrices/asserts.d.ts.map +1 -0
  45. package/build/matrices/asserts.js +396 -0
  46. package/build/matrices/asserts.js.map +1 -0
  47. package/build/matrices/asserts.spec.d.ts +2 -0
  48. package/build/matrices/asserts.spec.d.ts.map +1 -0
  49. package/build/matrices/asserts.spec.js +565 -0
  50. package/build/matrices/asserts.spec.js.map +1 -0
  51. package/build/matrices/core.d.ts +168 -0
  52. package/build/matrices/core.d.ts.map +1 -0
  53. package/build/matrices/core.js +457 -0
  54. package/build/matrices/core.js.map +1 -0
  55. package/build/matrices/core.spec.d.ts +2 -0
  56. package/build/matrices/core.spec.d.ts.map +1 -0
  57. package/build/matrices/core.spec.js +634 -0
  58. package/build/matrices/core.spec.js.map +1 -0
  59. package/build/matrices/decompositions.d.ts +326 -0
  60. package/build/matrices/decompositions.d.ts.map +1 -0
  61. package/build/matrices/decompositions.js +816 -0
  62. package/build/matrices/decompositions.js.map +1 -0
  63. package/build/matrices/decompositions.spec.d.ts +2 -0
  64. package/build/matrices/decompositions.spec.d.ts.map +1 -0
  65. package/build/matrices/decompositions.spec.js +195 -0
  66. package/build/matrices/decompositions.spec.js.map +1 -0
  67. package/build/matrices/index.d.ts +9 -0
  68. package/build/matrices/index.d.ts.map +1 -0
  69. package/build/matrices/index.js +9 -0
  70. package/build/matrices/index.js.map +1 -0
  71. package/build/matrices/linear-algebra.d.ts +64 -0
  72. package/build/matrices/linear-algebra.d.ts.map +1 -0
  73. package/build/matrices/linear-algebra.js +253 -0
  74. package/build/matrices/linear-algebra.js.map +1 -0
  75. package/build/matrices/linear-algebra.spec.d.ts +2 -0
  76. package/build/matrices/linear-algebra.spec.d.ts.map +1 -0
  77. package/build/matrices/linear-algebra.spec.js +355 -0
  78. package/build/matrices/linear-algebra.spec.js.map +1 -0
  79. package/build/matrices/normalization.d.ts +62 -0
  80. package/build/matrices/normalization.d.ts.map +1 -0
  81. package/build/matrices/normalization.js +167 -0
  82. package/build/matrices/normalization.js.map +1 -0
  83. package/build/matrices/normalization.spec.d.ts +2 -0
  84. package/build/matrices/normalization.spec.d.ts.map +1 -0
  85. package/build/matrices/normalization.spec.js +335 -0
  86. package/build/matrices/normalization.spec.js.map +1 -0
  87. package/build/matrices/transformations.d.ts +484 -0
  88. package/build/matrices/transformations.d.ts.map +1 -0
  89. package/build/matrices/transformations.js +592 -0
  90. package/build/matrices/transformations.js.map +1 -0
  91. package/build/matrices/transformations.spec.d.ts +2 -0
  92. package/build/matrices/transformations.spec.d.ts.map +1 -0
  93. package/build/matrices/transformations.spec.js +755 -0
  94. package/build/matrices/transformations.spec.js.map +1 -0
  95. package/build/matrices/types.d.ts +134 -0
  96. package/build/matrices/types.d.ts.map +1 -0
  97. package/build/matrices/types.js +6 -0
  98. package/build/matrices/types.js.map +1 -0
  99. package/build/quaternions/asserts.d.ts +77 -0
  100. package/build/quaternions/asserts.d.ts.map +1 -0
  101. package/build/quaternions/asserts.js +175 -0
  102. package/build/quaternions/asserts.js.map +1 -0
  103. package/build/quaternions/asserts.spec.d.ts +2 -0
  104. package/build/quaternions/asserts.spec.d.ts.map +1 -0
  105. package/build/quaternions/asserts.spec.js +320 -0
  106. package/build/quaternions/asserts.spec.js.map +1 -0
  107. package/build/quaternions/conversions.d.ts +73 -0
  108. package/build/quaternions/conversions.d.ts.map +1 -0
  109. package/build/quaternions/conversions.js +179 -0
  110. package/build/quaternions/conversions.js.map +1 -0
  111. package/build/quaternions/conversions.spec.d.ts +2 -0
  112. package/build/quaternions/conversions.spec.d.ts.map +1 -0
  113. package/build/quaternions/conversions.spec.js +344 -0
  114. package/build/quaternions/conversions.spec.js.map +1 -0
  115. package/build/quaternions/core.d.ts +203 -0
  116. package/build/quaternions/core.d.ts.map +1 -0
  117. package/build/quaternions/core.js +374 -0
  118. package/build/quaternions/core.js.map +1 -0
  119. package/build/quaternions/core.spec.d.ts +2 -0
  120. package/build/quaternions/core.spec.d.ts.map +1 -0
  121. package/build/quaternions/core.spec.js +294 -0
  122. package/build/quaternions/core.spec.js.map +1 -0
  123. package/build/quaternions/index.d.ts +7 -0
  124. package/build/quaternions/index.d.ts.map +1 -0
  125. package/build/quaternions/index.js +7 -0
  126. package/build/quaternions/index.js.map +1 -0
  127. package/build/quaternions/interpolation.d.ts +54 -0
  128. package/build/quaternions/interpolation.d.ts.map +1 -0
  129. package/build/quaternions/interpolation.js +201 -0
  130. package/build/quaternions/interpolation.js.map +1 -0
  131. package/build/quaternions/interpolation.spec.d.ts +2 -0
  132. package/build/quaternions/interpolation.spec.d.ts.map +1 -0
  133. package/build/quaternions/interpolation.spec.js +64 -0
  134. package/build/quaternions/interpolation.spec.js.map +1 -0
  135. package/build/quaternions/predefined.d.ts +36 -0
  136. package/build/quaternions/predefined.d.ts.map +1 -0
  137. package/build/quaternions/predefined.js +42 -0
  138. package/build/quaternions/predefined.js.map +1 -0
  139. package/build/quaternions/predefined.spec.d.ts +2 -0
  140. package/build/quaternions/predefined.spec.d.ts.map +1 -0
  141. package/build/quaternions/predefined.spec.js +35 -0
  142. package/build/quaternions/predefined.spec.js.map +1 -0
  143. package/build/quaternions/types.d.ts +55 -0
  144. package/build/quaternions/types.d.ts.map +1 -0
  145. package/build/quaternions/types.js +7 -0
  146. package/build/quaternions/types.js.map +1 -0
  147. package/build/random.d.ts +66 -0
  148. package/build/random.d.ts.map +1 -0
  149. package/build/random.js +115 -0
  150. package/build/random.js.map +1 -0
  151. package/build/random.spec.d.ts +2 -0
  152. package/build/random.spec.d.ts.map +1 -0
  153. package/build/random.spec.js +267 -0
  154. package/build/random.spec.js.map +1 -0
  155. package/build/vectors/asserts.d.ts +182 -0
  156. package/build/vectors/asserts.d.ts.map +1 -0
  157. package/build/vectors/asserts.js +285 -0
  158. package/build/vectors/asserts.js.map +1 -0
  159. package/build/vectors/asserts.spec.d.ts +2 -0
  160. package/build/vectors/asserts.spec.d.ts.map +1 -0
  161. package/build/vectors/asserts.spec.js +260 -0
  162. package/build/vectors/asserts.spec.js.map +1 -0
  163. package/build/vectors/core.d.ts +507 -0
  164. package/build/vectors/core.d.ts.map +1 -0
  165. package/build/vectors/core.js +825 -0
  166. package/build/vectors/core.js.map +1 -0
  167. package/build/vectors/core.spec.d.ts +2 -0
  168. package/build/vectors/core.spec.d.ts.map +1 -0
  169. package/build/vectors/core.spec.js +343 -0
  170. package/build/vectors/core.spec.js.map +1 -0
  171. package/build/vectors/index.d.ts +6 -0
  172. package/build/vectors/index.d.ts.map +1 -0
  173. package/build/vectors/index.js +6 -0
  174. package/build/vectors/index.js.map +1 -0
  175. package/build/vectors/interpolation.d.ts +404 -0
  176. package/build/vectors/interpolation.d.ts.map +1 -0
  177. package/build/vectors/interpolation.js +585 -0
  178. package/build/vectors/interpolation.js.map +1 -0
  179. package/build/vectors/interpolation.spec.d.ts +2 -0
  180. package/build/vectors/interpolation.spec.d.ts.map +1 -0
  181. package/build/vectors/interpolation.spec.js +378 -0
  182. package/build/vectors/interpolation.spec.js.map +1 -0
  183. package/build/vectors/predefined.d.ts +191 -0
  184. package/build/vectors/predefined.d.ts.map +1 -0
  185. package/build/vectors/predefined.js +191 -0
  186. package/build/vectors/predefined.js.map +1 -0
  187. package/build/vectors/predefined.spec.d.ts +2 -0
  188. package/build/vectors/predefined.spec.d.ts.map +1 -0
  189. package/build/vectors/predefined.spec.js +333 -0
  190. package/build/vectors/predefined.spec.js.map +1 -0
  191. package/build/vectors/types.d.ts +62 -0
  192. package/build/vectors/types.d.ts.map +1 -0
  193. package/build/vectors/types.js +6 -0
  194. package/build/vectors/types.js.map +1 -0
  195. package/package.json +75 -0
@@ -0,0 +1,825 @@
1
+ /**
2
+ * Core vector mathematics operations for linear algebra and geometric calculations.
3
+ * Provides a comprehensive set of vector operations with type safety and error checking.
4
+ */
5
+ import { Clamp } from '../clamp.js';
6
+ import { AssertVector, AssertVectors, AssertVectorValue, VectorError, AssertVector2, AssertVector3 } from './asserts.js';
7
+ /**
8
+ * Creates a deep copy of a vector.
9
+ * Essential for avoiding mutations when performing operations that should preserve the original vector.
10
+ *
11
+ * @template T - The vector type extending TVector
12
+ * @param vector - The vector to clone
13
+ * @returns A new vector with identical components
14
+ *
15
+ * @example
16
+ * const original = [1, 2, 3];
17
+ * const copy = VectorClone(original);
18
+ * copy[0] = 10; // original remains unchanged
19
+ */
20
+ export function VectorClone(vector) {
21
+ AssertVector(vector);
22
+ return vector.map((v) => v);
23
+ }
24
+ /**
25
+ * Compares two vectors for equality with optional tolerance for floating-point precision.
26
+ * Useful for comparing vectors that may have slight numerical differences due to calculations.
27
+ *
28
+ * @template T - The vector type extending TVector
29
+ * @param a - First vector to compare
30
+ * @param b - Second vector to compare
31
+ * @param tolerance - Maximum allowed difference between components (default: 0 for exact equality)
32
+ * @returns True if vectors are equal within tolerance, false otherwise
33
+ *
34
+ * @example
35
+ * const a = [1.0001, 2.0001];
36
+ * const b = [1.0002, 2.0002];
37
+ * const exactlyEqual = VectorEquals(a, b); // false
38
+ * const approximatelyEqual = VectorEquals(a, b, 0.001); // true
39
+ */
40
+ export function VectorEquals(a, b, tolerance = 0) {
41
+ AssertVectors([a, b]);
42
+ if (a.length !== b.length)
43
+ return false;
44
+ for (let i = 0; i < a.length; i++) {
45
+ const av = a[i];
46
+ AssertVectorValue(av, {});
47
+ const bv = b[i];
48
+ AssertVectorValue(bv, {});
49
+ if (tolerance !== 0) {
50
+ if (Math.abs(av - bv) > tolerance)
51
+ return false;
52
+ }
53
+ else if (av !== bv)
54
+ return false;
55
+ }
56
+ return true;
57
+ }
58
+ /**
59
+ * Converts a vector to a human-readable string representation.
60
+ * Useful for debugging, logging, and displaying vector values.
61
+ *
62
+ * @param vector - The vector to convert to string
63
+ * @param style - Output format: 'parens' for (x, y, z) or 'brackets' for [x, y, z]
64
+ * @returns String representation of the vector
65
+ *
66
+ * @example
67
+ * const vec = [1, 2, 3];
68
+ * const parens = VectorToString(vec, 'parens'); // "(1, 2, 3)"
69
+ * const brackets = VectorToString(vec, 'brackets'); // "[1, 2, 3]"
70
+ */
71
+ export function VectorToString(vector, style = 'parens') {
72
+ AssertVector(vector);
73
+ const components = vector.map((v) => v.toString()).join(', ');
74
+ if (style === 'parens') {
75
+ return `(${components})`;
76
+ }
77
+ else if (style === 'brackets') {
78
+ return `[${components}]`;
79
+ }
80
+ else {
81
+ throw new Error(`Invalid style: ${style}. Use 'parens' or 'brackets'.`);
82
+ }
83
+ }
84
+ /**
85
+ * Performs component-wise addition of two vectors.
86
+ * Fundamental operation for vector arithmetic, physics simulations, and geometric transformations.
87
+ *
88
+ * @template T - The vector type extending TVector
89
+ * @param a - First vector (augend)
90
+ * @param b - Second vector (addend)
91
+ * @returns New vector where each component is the sum of corresponding components
92
+ *
93
+ * @example
94
+ * const position = [10, 20, 30];
95
+ * const velocity = [1, -2, 0.5];
96
+ * const newPosition = VectorAdd(position, velocity); // [11, 18, 30.5]
97
+ */
98
+ export function VectorAdd(a, b) {
99
+ AssertVectors([a, b]);
100
+ const result = [];
101
+ for (let i = 0; i < a.length; i++) {
102
+ const av = a[i];
103
+ AssertVectorValue(av, {});
104
+ const bv = b[i];
105
+ AssertVectorValue(bv, {});
106
+ result.push(av + bv);
107
+ }
108
+ return result;
109
+ }
110
+ /**
111
+ * Performs component-wise subtraction of two vectors.
112
+ * Essential for calculating displacement, relative positions, and vector differences.
113
+ *
114
+ * @template T - The vector type extending TVector
115
+ * @param a - First vector (minuend)
116
+ * @param b - Second vector (subtrahend)
117
+ * @returns New vector where each component is the difference of corresponding components
118
+ *
119
+ * @example
120
+ * const target = [100, 50, 0];
121
+ * const current = [80, 30, 0];
122
+ * const direction = VectorSubtract(target, current); // [20, 20, 0]
123
+ */
124
+ export function VectorSubtract(a, b) {
125
+ AssertVectors([a, b]);
126
+ const result = [];
127
+ for (let i = 0; i < a.length; i++) {
128
+ const av = a[i];
129
+ AssertVectorValue(av, {}, { index: i });
130
+ const bv = b[i];
131
+ AssertVectorValue(bv, {}, { index: i });
132
+ result.push(av - bv);
133
+ }
134
+ return result;
135
+ }
136
+ /**
137
+ * Multiplies a vector by a scalar or performs component-wise multiplication with another vector.
138
+ * Scalar multiplication scales the vector magnitude; component-wise multiplication is useful for scaling factors.
139
+ *
140
+ * @template T - The vector type extending TVector
141
+ * @param a - Vector to multiply
142
+ * @param b - Scalar number or vector for component-wise multiplication
143
+ * @returns New vector with multiplied components
144
+ *
145
+ * @example
146
+ * const velocity = [10, 5, 0];
147
+ * const scaled = VectorMultiply(velocity, 2); // [20, 10, 0] - scalar multiplication
148
+ * const factors = [1, -1, 0.5];
149
+ * const componentWise = VectorMultiply(velocity, factors); // [10, -5, 0] - component-wise
150
+ */
151
+ export function VectorMultiply(a, b) {
152
+ const result = [];
153
+ if (Array.isArray(b)) {
154
+ if (b.length !== a.length)
155
+ throw new Error('Vector Size Mismatch');
156
+ for (let i = 0; i < a.length; i++) {
157
+ const av = a[i];
158
+ AssertVectorValue(av, {});
159
+ const bv = b[i];
160
+ AssertVectorValue(bv, {});
161
+ const prod = av * bv;
162
+ result.push(Object.is(prod, -0) ? 0 : prod);
163
+ }
164
+ }
165
+ else if (typeof b === 'number') {
166
+ for (const av of a) {
167
+ AssertVectorValue(av, {});
168
+ const prod = av * b;
169
+ result.push(Object.is(prod, -0) ? 0 : prod);
170
+ }
171
+ }
172
+ return result;
173
+ }
174
+ /**
175
+ * Calculates the Euclidean distance between two vectors.
176
+ * Fundamental for spatial calculations, collision detection, and proximity measurements.
177
+ *
178
+ * @param a - First vector
179
+ * @param b - Second vector
180
+ * @returns The straight-line distance between the two points represented by the vectors
181
+ *
182
+ * @example
183
+ * const pointA = [0, 0, 0];
184
+ * const pointB = [3, 4, 0];
185
+ * const distance = VectorDistance(pointA, pointB); // 5.0 (3-4-5 triangle)
186
+ */
187
+ export function VectorDistance(a, b) {
188
+ return Math.sqrt(VectorDistanceSquared(a, b));
189
+ }
190
+ /**
191
+ * Calculates the squared distance between two vectors.
192
+ * More efficient than VectorDistance when only relative distances matter,
193
+ * as it avoids the expensive square root operation.
194
+ *
195
+ * @param a - First vector
196
+ * @param b - Second vector
197
+ * @returns The squared distance between vectors
198
+ *
199
+ * @example
200
+ * const pointA = [1, 1];
201
+ * const pointB = [4, 5];
202
+ * const distSq = VectorDistanceSquared(pointA, pointB); // 25 (faster than distance comparison)
203
+ */
204
+ export function VectorDistanceSquared(a, b) {
205
+ AssertVectors([a, b]);
206
+ let sum = 0;
207
+ for (let i = 0; i < a.length; i++) {
208
+ const av = a[i];
209
+ AssertVectorValue(av, {});
210
+ const bv = b[i];
211
+ AssertVectorValue(bv, {});
212
+ sum += Math.pow(bv - av, 2);
213
+ }
214
+ return sum;
215
+ }
216
+ /**
217
+ * Calculates the dot product (scalar product) of two vectors.
218
+ * Fundamental operation for projections, angles, and determining vector relationships.
219
+ * Returns positive for acute angles, zero for perpendicular vectors, negative for obtuse angles.
220
+ *
221
+ * @param a - First vector
222
+ * @param b - Second vector
223
+ * @returns The dot product (scalar value)
224
+ *
225
+ * @example
226
+ * const forward = [0, 0, 1];
227
+ * const direction = [0, 0, 2];
228
+ * const dot = VectorDot(forward, direction); // 2 (same direction)
229
+ *
230
+ * const perpendicular = [1, 0, 0];
231
+ * const dotPerp = VectorDot(forward, perpendicular); // 0 (perpendicular)
232
+ */
233
+ export function VectorDot(a, b) {
234
+ AssertVectors([a, b]);
235
+ let dotProduct = 0;
236
+ for (let i = 0; i < a.length; i++) {
237
+ const av = a[i];
238
+ AssertVectorValue(av, {});
239
+ const bv = b[i];
240
+ AssertVectorValue(bv, {});
241
+ dotProduct += av * bv;
242
+ }
243
+ return dotProduct;
244
+ }
245
+ /**
246
+ * Normalizes a vector to unit length (magnitude of 1).
247
+ * Essential for direction vectors, surface normals, and unit calculations.
248
+ * Preserves direction while standardizing magnitude.
249
+ *
250
+ * @template T - The vector type extending TVector
251
+ * @param a - Vector to normalize
252
+ * @returns Unit vector in the same direction
253
+ * @throws {VectorError} If the vector is zero or has infinite magnitude
254
+ *
255
+ * @example
256
+ * const vector = [3, 4, 0];
257
+ * const normalized = VectorNormalize(vector); // [0.6, 0.8, 0] (magnitude = 1)
258
+ *
259
+ * const direction = [10, 0, 0];
260
+ * const unitDirection = VectorNormalize(direction); // [1, 0, 0]
261
+ */
262
+ export function VectorNormalize(a) {
263
+ AssertVector(a);
264
+ const magnitude = VectorMagnitude(a);
265
+ if (magnitude === 0)
266
+ throw new VectorError(`Cannot Normalize a Zero Vector: ${VectorToString(a)}`);
267
+ if (magnitude === Number.POSITIVE_INFINITY)
268
+ throw new VectorError(`Cannot Normalize a Vector with Infinite Magnitude: ${VectorToString(a)}`);
269
+ const result = VectorClone(a);
270
+ for (let i = 0; i < a.length; i++) {
271
+ const av = a[i];
272
+ AssertVectorValue(av, {});
273
+ result[i] = av / magnitude;
274
+ }
275
+ return result;
276
+ }
277
+ /**
278
+ * Calculates the magnitude (length) of a vector.
279
+ * Fundamental for distance calculations, normalization, and vector analysis.
280
+ *
281
+ * @param a - Vector to measure
282
+ * @returns The magnitude (length) of the vector
283
+ *
284
+ * @example
285
+ * const velocity = [3, 4, 0];
286
+ * const speed = VectorMagnitude(velocity); // 5.0
287
+ *
288
+ * const unitVector = [1, 0, 0];
289
+ * const unitLength = VectorMagnitude(unitVector); // 1.0
290
+ */
291
+ export function VectorMagnitude(a) {
292
+ AssertVector(a);
293
+ let sum = 0;
294
+ for (const av of a) {
295
+ AssertVectorValue(av, {});
296
+ sum += Math.pow(av, 2);
297
+ }
298
+ return Math.sqrt(sum);
299
+ }
300
+ /**
301
+ * Returns a vector with the absolute value of each component.
302
+ * Useful for distance calculations, bounding box calculations, and ensuring positive values.
303
+ *
304
+ * @template T - The vector type extending TVector
305
+ * @param a - Vector to process
306
+ * @returns New vector with absolute values of all components
307
+ *
308
+ * @example
309
+ * const vector = [-3, 4, -2];
310
+ * const absolute = VectorAbs(vector); // [3, 4, 2]
311
+ *
312
+ * const mixed = [1.5, -2.7, 0];
313
+ * const absValues = VectorAbs(mixed); // [1.5, 2.7, 0]
314
+ */
315
+ export function VectorAbs(a) {
316
+ AssertVector(a);
317
+ const result = [];
318
+ for (const av of a) {
319
+ AssertVectorValue(av, {});
320
+ result.push(Math.abs(av));
321
+ }
322
+ return result;
323
+ }
324
+ /**
325
+ * Checks if a vector is a zero vector (all components are zero).
326
+ * Important for validating input vectors and avoiding division by zero in calculations.
327
+ *
328
+ * @param vector - Vector to check
329
+ * @returns True if all components are zero, false otherwise
330
+ *
331
+ * @example
332
+ * const zero = [0, 0, 0];
333
+ * const isZero = VectorIsZero(zero); // true
334
+ *
335
+ * const notZero = [0, 0.001, 0];
336
+ * const isNotZero = VectorIsZero(notZero); // false
337
+ */
338
+ export function VectorIsZero(vector) {
339
+ return vector.every((v) => v === 0);
340
+ }
341
+ /**
342
+ * Calculates the angle between two vectors in radians.
343
+ * Essential for determining angular relationships, rotations, and orientations.
344
+ * Always returns a positive angle between 0 and π radians.
345
+ *
346
+ * @param a - First vector
347
+ * @param b - Second vector
348
+ * @returns Angle between vectors in radians (0 to π)
349
+ * @throws {VectorError} If either vector is zero
350
+ *
351
+ * @example
352
+ * const right = [1, 0, 0];
353
+ * const up = [0, 1, 0];
354
+ * const angle = VectorAngle(right, up); // π/2 (90 degrees)
355
+ *
356
+ * const forward = [0, 0, 1];
357
+ * const backward = [0, 0, -1];
358
+ * const oppositeAngle = VectorAngle(forward, backward); // π (180 degrees)
359
+ */
360
+ export function VectorAngle(a, b) {
361
+ AssertVectors([a, b]);
362
+ if (VectorIsZero(a) || VectorIsZero(b))
363
+ throw new VectorError('Cannot Calculate Angle with Zero Vectors');
364
+ const dot = VectorDot(a, b);
365
+ const magProduct = VectorMagnitude(a) * VectorMagnitude(b);
366
+ const cosTheta = Clamp(dot / magProduct, -1, 1);
367
+ return Math.acos(cosTheta);
368
+ }
369
+ /**
370
+ * Rotates a 2D vector by the specified angle in radians.
371
+ * Essential for 2D transformations, sprite rotations, and directional calculations.
372
+ *
373
+ * @param vector - 2D vector to rotate
374
+ * @param radians - Rotation angle in radians (positive = counterclockwise)
375
+ * @returns New rotated 2D vector
376
+ *
377
+ * @example
378
+ * const right = [1, 0];
379
+ * const rotated90 = Vector2Rotate(right, Math.PI / 2); // [0, 1] (up)
380
+ * const rotated180 = Vector2Rotate(right, Math.PI); // [-1, 0] (left)
381
+ */
382
+ export function Vector2Rotate(vector, radians) {
383
+ AssertVector2(vector);
384
+ const cos = Math.cos(radians);
385
+ const sin = Math.sin(radians);
386
+ const [v0, v1] = vector;
387
+ return [
388
+ (v0 * cos) - (v1 * sin),
389
+ (v0 * sin) + (v1 * cos),
390
+ ];
391
+ }
392
+ /**
393
+ * Creates a 2D unit vector from an angle in radians.
394
+ * Useful for creating directional vectors from angular measurements.
395
+ *
396
+ * @param radians - Angle in radians (0 = right, π/2 = up)
397
+ * @returns Unit vector pointing in the specified direction
398
+ *
399
+ * @example
400
+ * const right = Vector2FromAngle(0); // [1, 0]
401
+ * const up = Vector2FromAngle(Math.PI / 2); // [0, 1]
402
+ * const diagonal = Vector2FromAngle(Math.PI / 4); // [0.707, 0.707]
403
+ */
404
+ export function Vector2FromAngle(radians) {
405
+ return [Math.cos(radians), Math.sin(radians)];
406
+ }
407
+ /**
408
+ * Calculates the 2D cross product (returns a scalar).
409
+ * In 2D, the cross product represents the signed area of the parallelogram formed by the vectors.
410
+ * Useful for determining relative orientation and winding order.
411
+ *
412
+ * @param a - First 2D vector
413
+ * @param b - Second 2D vector
414
+ * @returns Scalar cross product (positive = counterclockwise, negative = clockwise)
415
+ *
416
+ * @example
417
+ * const right = [1, 0];
418
+ * const up = [0, 1];
419
+ * const cross = Vector2Cross(right, up); // 1 (counterclockwise)
420
+ * const crossReverse = Vector2Cross(up, right); // -1 (clockwise)
421
+ */
422
+ export function Vector2Cross(a, b) {
423
+ AssertVector2(a);
424
+ AssertVector2(b);
425
+ return (a[0] * b[1]) - (a[1] * b[0]);
426
+ }
427
+ /**
428
+ * Calculates the 3D rejection of vector a from vector b.
429
+ * Returns the component of vector a that is perpendicular to vector b.
430
+ * Useful for separating parallel and perpendicular components.
431
+ *
432
+ * @param a - Vector to reject from
433
+ * @param b - Vector to reject onto
434
+ * @returns Component of a perpendicular to b
435
+ * @throws {VectorError} If vector b is zero
436
+ *
437
+ * @example
438
+ * const force = [5, 3, 0];
439
+ * const surface = [1, 0, 0];
440
+ * const perpendicular = Vector3Reject(force, surface); // [0, 3, 0]
441
+ */
442
+ export function Vector3Reject(a, b) {
443
+ AssertVector3(a);
444
+ AssertVector3(b);
445
+ if (VectorIsZero(b))
446
+ throw new VectorError('Cannot compute rejection with a zero vector');
447
+ const projection = VectorProject(a, b);
448
+ return VectorSubtract(a, projection);
449
+ }
450
+ /**
451
+ * Projects vector a onto vector b.
452
+ * Returns the component of vector a that lies parallel to vector b.
453
+ * Essential for shadow calculations, force decomposition, and geometric projections.
454
+ *
455
+ * @template T - The vector type extending TVector
456
+ * @param a - Vector to project
457
+ * @param b - Vector to project onto
458
+ * @returns Component of a parallel to b
459
+ * @throws {VectorError} If vector b is zero
460
+ *
461
+ * @example
462
+ * const force = [5, 3, 0];
463
+ * const surface = [1, 0, 0];
464
+ * const parallel = VectorProject(force, surface); // [5, 0, 0]
465
+ */
466
+ export function VectorProject(a, b) {
467
+ AssertVectors([a, b]);
468
+ if (VectorIsZero(b))
469
+ throw new VectorError('Cannot project onto a zero vector');
470
+ const dot = VectorDot(a, b);
471
+ const magSquared = Math.pow(VectorMagnitude(b), 2);
472
+ const scalar = dot / magSquared;
473
+ const result = [];
474
+ for (const bv of b) {
475
+ AssertVectorValue(bv, {});
476
+ result.push(scalar * bv);
477
+ }
478
+ return result;
479
+ }
480
+ /**
481
+ * Reflects an incident vector across a 3D normal (specialized version).
482
+ * This is a specialized version of VectorReflect for 3D vectors.
483
+ * Automatically normalizes the normal vector for consistent results.
484
+ *
485
+ * @param incident - The incoming vector to reflect
486
+ * @param normal - The surface normal (will be normalized automatically)
487
+ * @returns The reflected vector
488
+ * @throws {VectorError} If the normal is a zero vector
489
+ *
490
+ * @example
491
+ * const incoming = [1, -1, 0];
492
+ * const normal = [0, 1, 0]; // surface normal (upward)
493
+ * const reflected = Vector3Reflect(incoming, normal); // [1, 1, 0]
494
+ */
495
+ export function Vector3Reflect(incident, normal) {
496
+ AssertVector3(incident);
497
+ AssertVector3(normal);
498
+ if (VectorIsZero(normal))
499
+ throw new VectorError('Cannot reflect across a zero normal');
500
+ const normalizedNormal = VectorNormalize(normal);
501
+ return VectorReflect(incident, normalizedNormal);
502
+ }
503
+ /**
504
+ * Calculates the 3D cross product of two vectors.
505
+ * Returns a vector perpendicular to both input vectors.
506
+ * Essential for surface normals, torque calculations, and 3D rotations.
507
+ *
508
+ * @param a - First 3D vector
509
+ * @param b - Second 3D vector
510
+ * @returns Vector perpendicular to both a and b (following right-hand rule)
511
+ *
512
+ * @example
513
+ * const right = [1, 0, 0];
514
+ * const forward = [0, 0, 1];
515
+ * const up = Vector3Cross(right, forward); // [0, 1, 0]
516
+ *
517
+ * const normal = Vector3Cross([1, 0, 0], [0, 1, 0]); // [0, 0, 1]
518
+ */
519
+ export function Vector3Cross(a, b) {
520
+ AssertVector3(a);
521
+ AssertVector3(b);
522
+ return [
523
+ (a[1] * b[2]) - (a[2] * b[1]),
524
+ (a[2] * b[0]) - (a[0] * b[2]),
525
+ (a[0] * b[1]) - (a[1] * b[0]),
526
+ ];
527
+ }
528
+ /**
529
+ * Calculates the magnitude of the 3D cross product.
530
+ * Equivalent to the area of the parallelogram formed by the two vectors.
531
+ * Useful for area calculations and determining vector orthogonality.
532
+ *
533
+ * @param a - First 3D vector
534
+ * @param b - Second 3D vector
535
+ * @returns Magnitude of the cross product
536
+ *
537
+ * @example
538
+ * const side1 = [3, 0, 0];
539
+ * const side2 = [0, 4, 0];
540
+ * const area = VectorCrossMagnitude(side1, side2); // 12 (area of rectangle)
541
+ */
542
+ export function VectorCrossMagnitude(a, b) {
543
+ AssertVector3(a);
544
+ AssertVector3(b);
545
+ const c = Vector3Cross(a, b);
546
+ return Math.sqrt((c[0] * c[0]) + (c[1] * c[1]) + (c[2] * c[2]));
547
+ }
548
+ /**
549
+ * Calculates the scalar triple product of three 3D vectors.
550
+ * Returns the signed volume of the parallelepiped formed by the three vectors.
551
+ * Useful for determining orientation and volume calculations.
552
+ *
553
+ * @param a - First 3D vector
554
+ * @param b - Second 3D vector
555
+ * @param c - Third 3D vector
556
+ * @returns Signed volume (positive = right-handed orientation)
557
+ *
558
+ * @example
559
+ * const x = [1, 0, 0];
560
+ * const y = [0, 1, 0];
561
+ * const z = [0, 0, 1];
562
+ * const volume = Vector3ScalarTripleProduct(x, y, z); // 1 (unit cube)
563
+ */
564
+ export function Vector3ScalarTripleProduct(a, b, c) {
565
+ AssertVector3(a);
566
+ AssertVector3(b);
567
+ AssertVector3(c);
568
+ const crossProduct = Vector3Cross(b, c);
569
+ return VectorDot(a, crossProduct);
570
+ }
571
+ /**
572
+ * Calculates the vector triple product of three 3D vectors.
573
+ * Implements the formula: a × (b × c)
574
+ * Useful for advanced geometric calculations and physics simulations.
575
+ *
576
+ * @param a - First 3D vector
577
+ * @param b - Second 3D vector
578
+ * @param c - Third 3D vector
579
+ * @returns Vector result of a × (b × c)
580
+ *
581
+ * @example
582
+ * const a = [1, 0, 0];
583
+ * const b = [0, 1, 0];
584
+ * const c = [0, 0, 1];
585
+ * const result = Vector3TripleProduct(a, b, c); // [0, 0, 0]
586
+ */
587
+ export function Vector3TripleProduct(a, b, c) {
588
+ AssertVector3(a);
589
+ AssertVector3(b);
590
+ AssertVector3(c);
591
+ const crossProduct = Vector3Cross(b, c);
592
+ return Vector3Cross(a, crossProduct);
593
+ }
594
+ /**
595
+ * Reflects a vector across a normal surface.
596
+ * Simulates perfect reflection like light bouncing off a mirror.
597
+ * The normal vector is automatically normalized for consistent results.
598
+ *
599
+ * @template T - The vector type extending TVector
600
+ * @param incident - The incoming vector to reflect
601
+ * @param normal - The surface normal vector
602
+ * @returns The reflected vector
603
+ *
604
+ * @example
605
+ * const incoming = [1, -1, 0];
606
+ * const wall = [0, 1, 0]; // vertical wall normal
607
+ * const bounced = VectorReflect(incoming, wall); // [1, 1, 0]
608
+ */
609
+ export function VectorReflect(incident, normal) {
610
+ AssertVectors([incident, normal]);
611
+ const normalizedNormal = VectorNormalize(normal);
612
+ const dot = VectorDot(incident, normalizedNormal);
613
+ const result = [];
614
+ for (let i = 0; i < incident.length; i++) {
615
+ const iv = incident[i];
616
+ AssertVectorValue(iv, {});
617
+ const nnv = normalizedNormal[i];
618
+ AssertVectorValue(nnv, {});
619
+ result.push(iv - (2 * dot * nnv));
620
+ }
621
+ return result;
622
+ }
623
+ /**
624
+ * Negates all components of a vector (multiplies by -1).
625
+ * Creates a vector pointing in the exact opposite direction.
626
+ * Handles special case of zero to avoid negative zero (-0).
627
+ *
628
+ * @template T - The vector type extending TVector
629
+ * @param a - Vector to negate
630
+ * @returns Vector with all components negated
631
+ *
632
+ * @example
633
+ * const forward = [0, 0, 1];
634
+ * const backward = VectorNegate(forward); // [0, 0, -1]
635
+ *
636
+ * const velocity = [5, -3, 2];
637
+ * const opposite = VectorNegate(velocity); // [-5, 3, -2]
638
+ */
639
+ export function VectorNegate(a) {
640
+ const result = [];
641
+ for (const av of a) {
642
+ AssertVectorValue(av, {});
643
+ // Special handling for zero to avoid negative zero (-0)
644
+ if (av === 0) {
645
+ result.push(0);
646
+ }
647
+ else {
648
+ result.push(-1 * av);
649
+ }
650
+ }
651
+ return result;
652
+ }
653
+ /**
654
+ * Divides a vector by a scalar or performs component-wise division with another vector.
655
+ * Scalar division scales the vector magnitude down; component-wise division is the inverse of component-wise multiplication.
656
+ *
657
+ * @template T - The vector type extending TVector
658
+ * @param a - Vector to divide (dividend)
659
+ * @param b - Scalar number or vector for component-wise division (divisor)
660
+ * @returns New vector with divided components
661
+ * @throws {VectorError} If any divisor component is zero
662
+ *
663
+ * @example
664
+ * const velocity = [20, 10, 0];
665
+ * const halved = VectorDivide(velocity, 2); // [10, 5, 0] - scalar division
666
+ * const factors = [2, 5, 1];
667
+ * const componentWise = VectorDivide(velocity, factors); // [10, 2, 0] - component-wise
668
+ */
669
+ export function VectorDivide(a, b) {
670
+ const result = [];
671
+ if (Array.isArray(b)) {
672
+ if (b.length !== a.length)
673
+ throw new VectorError('Vector Size Mismatch');
674
+ for (let i = 0; i < a.length; i++) {
675
+ const av = a[i];
676
+ AssertVectorValue(av, {});
677
+ const bv = b[i];
678
+ AssertVectorValue(bv, {});
679
+ if (bv === 0)
680
+ throw new VectorError(`Division by zero at component [${i}]`);
681
+ const quot = av / bv;
682
+ result.push(Object.is(quot, -0) ? 0 : quot);
683
+ }
684
+ }
685
+ else if (typeof b === 'number') {
686
+ if (b === 0)
687
+ throw new VectorError('Division by zero scalar');
688
+ for (const av of a) {
689
+ AssertVectorValue(av, {});
690
+ const quot = av / b;
691
+ result.push(Object.is(quot, -0) ? 0 : quot);
692
+ }
693
+ }
694
+ return result;
695
+ }
696
+ /**
697
+ * Clamps each component of a vector between the corresponding min and max values.
698
+ * Can accept scalar min/max (same bounds for all components) or vectors for per-component bounds.
699
+ * Mirrors the scalar `Clamp` function for vector operations.
700
+ *
701
+ * @template T - The vector type extending TVector
702
+ * @param a - Vector whose components are to be clamped
703
+ * @param min - Minimum value (scalar applied to all components, or vector for per-component bounds)
704
+ * @param max - Maximum value (scalar applied to all components, or vector for per-component bounds)
705
+ * @returns New vector with each component clamped between min and max
706
+ *
707
+ * @example
708
+ * const v = [5, -3, 12, 0];
709
+ * VectorClamp(v, 0, 10); // [5, 0, 10, 0] - scalar bounds
710
+ *
711
+ * const mins = [0, -5, 0, -1];
712
+ * const maxs = [10, 5, 8, 1];
713
+ * VectorClamp(v, mins, maxs); // [5, -3, 8, 0] - per-component bounds
714
+ */
715
+ export function VectorClamp(a, min, max) {
716
+ AssertVector(a);
717
+ const result = [];
718
+ for (let i = 0; i < a.length; i++) {
719
+ const av = a[i];
720
+ AssertVectorValue(av, {});
721
+ const minV = Array.isArray(min) ? min[i] : min;
722
+ const maxV = Array.isArray(max) ? max[i] : max;
723
+ result.push(Math.max(minV, Math.min(av, maxV)));
724
+ }
725
+ return result;
726
+ }
727
+ /**
728
+ * Limits the magnitude of a vector to a maximum value.
729
+ * If the vector's magnitude exceeds the limit, scales it down proportionally.
730
+ * Preserves direction while constraining magnitude.
731
+ *
732
+ * @template T - The vector type extending TVector
733
+ * @param a - Vector to limit
734
+ * @param max - Maximum allowed magnitude
735
+ * @returns Vector with magnitude limited to max
736
+ * @throws {VectorError} If max is negative
737
+ *
738
+ * @example
739
+ * const velocity = [15, 20, 0]; // magnitude ≈ 25
740
+ * const limited = VectorLimit(velocity, 10); // magnitude = 10, same direction
741
+ *
742
+ * const small = [1, 1, 0]; // magnitude ≈ 1.414
743
+ * const unchanged = VectorLimit(small, 5); // unchanged since already under limit
744
+ */
745
+ export function VectorLimit(a, max) {
746
+ if (max < 0)
747
+ throw new VectorError('Maximum magnitude cannot be negative');
748
+ const magnitude = VectorMagnitude(a);
749
+ if (magnitude <= max || magnitude === 0)
750
+ return VectorClone(a);
751
+ const scaleFactor = max / magnitude;
752
+ return VectorMultiply(a, scaleFactor);
753
+ }
754
+ /**
755
+ * Validates if the input is a properly formatted vector.
756
+ * Performs comprehensive validation without throwing errors.
757
+ * Useful for input validation and defensive programming.
758
+ *
759
+ * @param vector - Input to validate
760
+ * @returns True if input is a valid vector, false otherwise
761
+ *
762
+ * @example
763
+ * const valid = VectorIsValid([1, 2, 3]); // true
764
+ * const invalid = VectorIsValid("not a vector"); // false
765
+ * const nullVector = VectorIsValid(null); // false
766
+ * const emptyArray = VectorIsValid([]); // depends on implementation
767
+ */
768
+ export function VectorIsValid(vector) {
769
+ try {
770
+ AssertVector(vector);
771
+ return true;
772
+ }
773
+ catch {
774
+ return false;
775
+ }
776
+ }
777
+ /**
778
+ * Performs Gram-Schmidt orthogonalization on a set of vectors.
779
+ * Converts a set of linearly independent vectors into an orthogonal (or orthonormal) set.
780
+ * Essential for creating coordinate systems and orthogonal bases.
781
+ *
782
+ * @template T - The vector type extending TVector
783
+ * @param vectors - Array of vectors to orthogonalize
784
+ * @param normalize - Whether to normalize the resulting vectors (default: false)
785
+ * @returns Array of orthogonal (or orthonormal) vectors
786
+ * @throws {VectorError} If vectors are linearly dependent or invalid
787
+ *
788
+ * @example
789
+ * const vectors = [[1, 1, 0], [1, 0, 1], [0, 1, 1]];
790
+ * const orthogonal = VectorGramSchmidt(vectors); // Orthogonal set
791
+ * const orthonormal = VectorGramSchmidt(vectors, true); // Orthonormal set
792
+ */
793
+ export function VectorGramSchmidt(vectors, normalize = false) {
794
+ if (vectors.length === 0)
795
+ throw new VectorError('GramSchmidt: Empty Vector Set');
796
+ const [firstVector] = vectors;
797
+ if (!firstVector)
798
+ throw new VectorError('GramSchmidt: Undefined First Vector');
799
+ const dimension = firstVector.length;
800
+ for (const [i, vector] of vectors.entries()) {
801
+ AssertVector(vector);
802
+ if (vector.length !== dimension)
803
+ throw new VectorError(`GramSchmidt: Vector at index ${i} has different dimension than first vector. Expected ${dimension}, got ${vector.length}`);
804
+ if (VectorIsZero(vector))
805
+ throw new VectorError(`GramSchmidt: Vector at index ${i} is a zero vector. Cannot orthogonalize zero vectors.`);
806
+ }
807
+ const result = [];
808
+ for (const [i, currentVector] of vectors.entries()) {
809
+ AssertVector(currentVector);
810
+ let orthogonalVector = VectorClone(currentVector);
811
+ for (let j = 0; j < i; j++) {
812
+ const previousVector = result[j];
813
+ AssertVector(previousVector);
814
+ const projection = VectorProject(currentVector, previousVector);
815
+ orthogonalVector = VectorSubtract(orthogonalVector, projection);
816
+ }
817
+ if (VectorIsZero(orthogonalVector))
818
+ throw new VectorError(`GramSchmidt: Vector at index ${i} is linearly dependent on previous vectors. Cannot orthogonalize linearly dependent vectors.`);
819
+ if (normalize)
820
+ orthogonalVector = VectorNormalize(orthogonalVector);
821
+ result.push(orthogonalVector);
822
+ }
823
+ return result;
824
+ }
825
+ //# sourceMappingURL=core.js.map