@inglorious/utils 3.5.3 → 3.6.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inglorious/utils",
3
- "version": "3.5.3",
3
+ "version": "3.6.0",
4
4
  "description": "A set of general-purpose utility functions designed with functional programming principles in mind.",
5
5
  "author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "prettier": "^3.6.2",
42
42
  "vite": "^7.1.3",
43
43
  "vitest": "^1.6.1",
44
- "@inglorious/eslint-config": "1.0.0"
44
+ "@inglorious/eslint-config": "1.0.1"
45
45
  },
46
46
  "engines": {
47
47
  "node": ">= 22"
@@ -1,19 +1,31 @@
1
1
  /**
2
2
  * Composes multiple functions from right to left, as if every function wraps the next one.
3
+ * The first function (rightmost) can take multiple arguments; the remaining functions must be unary.
3
4
  *
4
5
  * @param {...Function} fns - Functions to compose.
5
- * @returns {Function} A function that takes an initial value and applies the composed functions.
6
+ * @returns {Function} A function that takes the initial arguments and applies the composed functions.
6
7
  */
7
8
  export function compose(...fns) {
8
- return (x) => fns.reduceRight((acc, fn) => fn(acc), x)
9
+ if (!fns.length) {
10
+ return (x) => x
11
+ }
12
+
13
+ const [last, ...rest] = fns.reverse()
14
+ return (...args) => rest.reduce((acc, fn) => fn(acc), last(...args))
9
15
  }
10
16
 
11
17
  /**
12
18
  * Pipes multiple functions from left to right, as if the functions are applied one by one.
19
+ * The first function (leftmost) can take multiple arguments; the remaining functions must be unary.
13
20
  *
14
21
  * @param {...Function} fns - Functions to pipe.
15
- * @returns {Function} A function that takes an initial value and applies the piped functions.
22
+ * @returns {Function} A function that takes the initial arguments and applies the piped functions.
16
23
  */
17
24
  export function pipe(...fns) {
18
- return (x) => fns.reduce((acc, fn) => fn(acc), x)
25
+ if (!fns.length) {
26
+ return (x) => x
27
+ }
28
+
29
+ const [first, ...rest] = fns
30
+ return (...args) => rest.reduce((acc, fn) => fn(acc), first(...args))
19
31
  }
@@ -2,22 +2,50 @@ import { expect, test } from "vitest"
2
2
 
3
3
  import { compose, pipe } from "./functions.js"
4
4
 
5
- test("it should compose functions", () => {
5
+ test("it should compose unary functions", () => {
6
6
  const shout = (x) => x.toUpperCase()
7
7
  const punctuate = (mark) => (x) => `${x}${mark}`
8
8
  const html = (tag) => (x) => `<${tag}>${x}</${tag}>`
9
9
 
10
10
  const fn = compose(html("p"), punctuate("!"), shout)
11
-
12
11
  expect(fn("Hello world")).toBe("<p>HELLO WORLD!</p>")
13
12
  })
14
13
 
15
- test("it should pipe functions", () => {
14
+ test("it should compose functions with multiple initial arguments", () => {
15
+ const add = (a, b) => a + b
16
+ const square = (x) => x * x
17
+ const half = (x) => x / 2
18
+
19
+ const fn = compose(half, square, add) // half(square(add(2, 3)))
20
+ expect(fn(2, 3)).toBe(12.5)
21
+ })
22
+
23
+ test("it should return an identity-like function if compose is called with no arguments", () => {
24
+ const fn = compose()
25
+ expect(fn(42)).toBe(42)
26
+ expect(fn({ a: 1 })).toStrictEqual({ a: 1 })
27
+ })
28
+
29
+ test("it should pipe unary functions", () => {
16
30
  const shout = (x) => x.toUpperCase()
17
31
  const punctuate = (mark) => (x) => `${x}${mark}`
18
32
  const html = (tag) => (x) => `<${tag}>${x}</${tag}>`
19
33
 
20
34
  const fn = pipe(shout, punctuate("!"), html("p"))
21
-
22
35
  expect(fn("Hello world")).toBe("<p>HELLO WORLD!</p>")
23
36
  })
37
+
38
+ test("it should pipe functions with multiple initial arguments", () => {
39
+ const add = (a, b) => a + b
40
+ const square = (x) => x * x
41
+ const half = (x) => x / 2
42
+
43
+ const fn = pipe(add, square, half) // half(square(add(2, 3)))
44
+ expect(fn(2, 3)).toBe(12.5)
45
+ })
46
+
47
+ test("it should return an identity-like function if pipe is called with no arguments", () => {
48
+ const fn = pipe()
49
+ expect(fn(42)).toBe(42)
50
+ expect(fn({ a: 1 })).toStrictEqual({ a: 1 })
51
+ })
@@ -54,11 +54,15 @@ export function isClose(num1, num2, tolerance = DEFAULT_TOLERANCE) {
54
54
 
55
55
  /**
56
56
  * Computes the modulus of two numbers, ensuring a positive result.
57
+ * If the divisor is zero, it returns the dividend to avoid `NaN`.
57
58
  * @param {number} dividend - The number to be divided.
58
59
  * @param {number} divisor - The number to divide by.
59
60
  * @returns {number} The modulus result.
60
61
  */
61
62
  export function mod(dividend, divisor) {
63
+ if (!divisor) {
64
+ return dividend
65
+ }
62
66
  return ((dividend % divisor) + divisor) % divisor
63
67
  }
64
68
 
@@ -154,6 +154,13 @@ test("it should convert a negative float number to a range between -1 and 1", ()
154
154
  expect(mod(num, divisor)).toBe(expectedResult)
155
155
  })
156
156
 
157
+ test("it should return the dividend if the divisor is zero", () => {
158
+ const num = 42
159
+ const divisor = 0
160
+
161
+ expect(mod(num, divisor)).toBe(num)
162
+ })
163
+
157
164
  test("it should return one if number is positive", () => {
158
165
  const num = 42
159
166
  const expectedResult = 1
@@ -96,6 +96,16 @@ export function createVector(magnitude, angle) {
96
96
  return scale(fromAngle(angle), magnitude)
97
97
  }
98
98
 
99
+ /**
100
+ * Divides a scalar by each component of the vector.
101
+ * @param {number} scalar - The dividend.
102
+ * @param {Vector} vector - The divisor vector.
103
+ * @returns {Vector} The resulting vector.
104
+ */
105
+ export function divideBy(scalar, vector) {
106
+ return v(...vector.map((coordinate) => scalar / coordinate))
107
+ }
108
+
99
109
  /**
100
110
  * Divides each component of the vector by the given scalar.
101
111
  * @param {Vector} vector - The input vector.
@@ -157,6 +167,16 @@ export function mod(vector, divisor) {
157
167
  return v(...vector.map((coordinate) => nMod(coordinate, divisor)))
158
168
  }
159
169
 
170
+ /**
171
+ * Calculates the modulus of a scalar with each component of the vector.
172
+ * @param {number} scalar - The dividend.
173
+ * @param {Vector} vector - The divisor vector.
174
+ * @returns {Vector} The resulting vector.
175
+ */
176
+ export function modOf(scalar, vector) {
177
+ return v(...vector.map((coordinate) => nMod(scalar, coordinate)))
178
+ }
179
+
160
180
  /**
161
181
  * Multiplies each component of the vector by the given scalar.
162
182
  * @param {Vector} vector - The input vector.
@@ -184,16 +204,14 @@ export function power(vector, exponent) {
184
204
  }
185
205
 
186
206
  /**
187
- * Alias for the multiply function.
188
- * @type {typeof multiply}
189
- */
190
- export const scale = multiply
191
-
192
- /**
193
- * Alias for the multiply function.
194
- * @type {typeof multiply}
207
+ * Raises a scalar to the power of each component of the vector.
208
+ * @param {number} scalar - The base value.
209
+ * @param {Vector} vector - The exponent vector.
210
+ * @returns {Vector} The resulting vector.
195
211
  */
196
- export const times = multiply
212
+ export function powerOf(scalar, vector) {
213
+ return v(...vector.map((coordinate) => scalar ** coordinate))
214
+ }
197
215
 
198
216
  /**
199
217
  * Normalizes the vector to have a magnitude of 1.
@@ -228,6 +246,12 @@ export function rotate(vector, angle) {
228
246
  return is2D ? to2D(result) : result
229
247
  }
230
248
 
249
+ /**
250
+ * Alias for the multiply function.
251
+ * @type {typeof multiply}
252
+ */
253
+ export const scale = multiply
254
+
231
255
  /**
232
256
  * Sets the angle of the vector in the XZ plane while maintaining its magnitude.
233
257
  * @param {Vector} vector - The input vector.
@@ -279,6 +303,12 @@ export function snap(vector, precision = DEFAULT_PRECISION) {
279
303
  )
280
304
  }
281
305
 
306
+ /**
307
+ * Alias for the multiply function.
308
+ * @type {typeof multiply}
309
+ */
310
+ export const times = multiply
311
+
282
312
  /**
283
313
  * Converts a 3D vector [x, y, z] into a 2D vector [x, z].
284
314
  * @param {Vector3} vector - A 3D vector represented as [x, y, z].
@@ -10,14 +10,17 @@ import {
10
10
  conjugate,
11
11
  createVector,
12
12
  divide,
13
+ divideBy,
13
14
  from2D,
14
15
  fromAngle,
15
16
  isVector,
16
17
  magnitude,
17
18
  mod,
19
+ modOf,
18
20
  multiply,
19
21
  normalize,
20
22
  power,
23
+ powerOf,
21
24
  rotate,
22
25
  setAngle,
23
26
  setMagnitude,
@@ -104,6 +107,14 @@ test("it should divide a vector by a scalar", () => {
104
107
  expect(divide(vector, scalar)).toStrictEqual(expectedResult)
105
108
  })
106
109
 
110
+ test("it should divide a scalar by a vector", () => {
111
+ const scalar = 12
112
+ const vector = v(4, 8, 12)
113
+ const expectedResult = v(3, 1.5, 1)
114
+
115
+ expect(divideBy(scalar, vector)).toStrictEqual(expectedResult)
116
+ })
117
+
107
118
  test("it should build a 3D vector from a 2D one", () => {
108
119
  const vector = v(3, 4)
109
120
  const expectedResult = v(3, 0, 4)
@@ -146,6 +157,14 @@ test("it should apply the mod operator (aka remainder) on a vector", () => {
146
157
  expect(mod(vector, divisor)).toStrictEqual(expectedResult)
147
158
  })
148
159
 
160
+ test("it should apply the mod operator of a scalar with a vector", () => {
161
+ const scalar = 18
162
+ const vector = v(10, 12, -18)
163
+ const expectedResult = v(8, 6, -0)
164
+
165
+ expect(modOf(scalar, vector)).toStrictEqual(expectedResult)
166
+ })
167
+
149
168
  test("it should multiply a vector with a scalar (aka times)", () => {
150
169
  const vector = v(1, 2, 3)
151
170
  const scalar = 4
@@ -176,6 +195,14 @@ test("it should raise each component of a vector to the given exponent (aka pow)
176
195
  expect(power(vector, exponent)).toStrictEqual(expectedResult)
177
196
  })
178
197
 
198
+ test("it should raise a scalar to the power of each component of a vector", () => {
199
+ const scalar = 2
200
+ const vector = v(1, 2, 3)
201
+ const expectedResult = v(2, 4, 8)
202
+
203
+ expect(powerOf(scalar, vector)).toStrictEqual(expectedResult)
204
+ })
205
+
179
206
  test("it should rotate a 2D vector by a certain angle", () => {
180
207
  const vector = v(1, 0)
181
208
  const angle = pi() / 4
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import { v } from "../v.js"
8
+ import { mod as nMod } from "./numbers.js"
8
9
  import { magnitude, shift } from "./vector.js"
9
10
 
10
11
  /**
@@ -31,6 +32,15 @@ export function distance(...vectors) {
31
32
  return magnitude(subtract(...vectors))
32
33
  }
33
34
 
35
+ /**
36
+ * Computes the component-wise division of multiple vectors.
37
+ * @param {...Vector2 | Vector3} vectors - The vectors to divide.
38
+ * @returns {Vector2 | Vector3} The resulting vector.
39
+ */
40
+ export function divide(...vectors) {
41
+ return v(...vectors.reduce(divideCoordinates))
42
+ }
43
+
34
44
  /**
35
45
  * Computes the dot product of multiple vectors.
36
46
  * @param {...Vector2 | Vector3} vectors - The vectors to compute the dot product for.
@@ -42,6 +52,39 @@ export function dot(...vectors) {
42
52
  .reduce((coord1, coord2) => coord1 + coord2)
43
53
  }
44
54
 
55
+ /**
56
+ * Alias for the multiply function.
57
+ * @type {typeof multiply}
58
+ */
59
+ export const hadamard = multiply
60
+
61
+ /**
62
+ * Computes the component-wise modulus of multiple vectors.
63
+ * @param {...Vector2 | Vector3} vectors - The vectors to compute the modulus for.
64
+ * @returns {Vector2 | Vector3} The resulting vector after the modulus.
65
+ */
66
+ export function mod(...vectors) {
67
+ return v(...vectors.reduce(modCoordinates))
68
+ }
69
+
70
+ /**
71
+ * Computes the component-wise multiplication of multiple vectors (Hadamard product).
72
+ * @param {...Vector2 | Vector3} vectors - The vectors to multiply.
73
+ * @returns {Vector2 | Vector3} The resulting vector.
74
+ */
75
+ export function multiply(...vectors) {
76
+ return v(...vectors.reduce(multiplyCoordinates))
77
+ }
78
+
79
+ /**
80
+ * Computes the component-wise power of multiple vectors.
81
+ * @param {...Vector2 | Vector3} vectors - The vectors to compute the power for.
82
+ * @returns {Vector2 | Vector3} The resulting vector after the power.
83
+ */
84
+ export function power(...vectors) {
85
+ return v(...vectors.reduce(powerCoordinates))
86
+ }
87
+
45
88
  /**
46
89
  * Alias for the dot product function.
47
90
  * @type {typeof dot}
@@ -92,6 +135,48 @@ function subtractCoordinates(vector1, vector2) {
92
135
  return v(...vector1.map((coordinate, index) => coordinate - vector2[index]))
93
136
  }
94
137
 
138
+ /**
139
+ * Divides the coordinates of two vectors component-wise.
140
+ * @param {Vector2 | Vector3} vector1 - The dividend vector.
141
+ * @param {Vector2 | Vector3} vector2 - The divisor vector.
142
+ * @returns {Vector2 | Vector3} The resulting vector.
143
+ */
144
+ function divideCoordinates(vector1, vector2) {
145
+ return v(...vector1.map((coordinate, index) => coordinate / vector2[index]))
146
+ }
147
+
148
+ /**
149
+ * Computes the component-wise modulus of two vectors.
150
+ * @param {Vector2 | Vector3} vector1 - The first vector.
151
+ * @param {Vector2 | Vector3} vector2 - The second vector.
152
+ * @returns {Vector2 | Vector3} The resulting vector after the modulus.
153
+ */
154
+ function modCoordinates(vector1, vector2) {
155
+ return v(
156
+ ...vector1.map((coordinate, index) => nMod(coordinate, vector2[index])),
157
+ )
158
+ }
159
+
160
+ /**
161
+ * Multiplies the coordinates of two vectors component-wise.
162
+ * @param {Vector2 | Vector3} vector1 - The first vector.
163
+ * @param {Vector2 | Vector3} vector2 - The second vector.
164
+ * @returns {Vector2 | Vector3} The resulting vector.
165
+ */
166
+ function multiplyCoordinates(vector1, vector2) {
167
+ return v(...vector1.map((coordinate, index) => coordinate * vector2[index]))
168
+ }
169
+
170
+ /**
171
+ * Raises the coordinates of the first vector to the power of the second vector's coordinates.
172
+ * @param {Vector2 | Vector3} vector1 - The base vector.
173
+ * @param {Vector2 | Vector3} vector2 - The exponent vector.
174
+ * @returns {Vector2 | Vector3} The resulting vector.
175
+ */
176
+ function powerCoordinates(vector1, vector2) {
177
+ return v(...vector1.map((coordinate, index) => coordinate ** vector2[index]))
178
+ }
179
+
95
180
  /**
96
181
  * Computes the cross product of two vectors' coordinates.
97
182
  * @param {Vector3} vector1 - The first vector.
@@ -1,7 +1,16 @@
1
1
  import { expect, test } from "vitest"
2
2
 
3
3
  import { v } from "../v.js"
4
- import { cross, distance, dot, subtract, sum } from "./vectors.js"
4
+ import {
5
+ cross,
6
+ distance,
7
+ divide,
8
+ dot,
9
+ multiply,
10
+ power,
11
+ subtract,
12
+ sum,
13
+ } from "./vectors.js"
5
14
 
6
15
  test("it should compute the cross product between two vectors (aka vectorProduct)", () => {
7
16
  const vector1 = v(1, 2, 3)
@@ -25,6 +34,13 @@ test("it should compute the distance between multiple vectors", () => {
25
34
  expect(distance(...vectors)).toStrictEqual(expectedResult)
26
35
  })
27
36
 
37
+ test("it should divide multiple vectors component-wise", () => {
38
+ const vectors = [v(80, 40, 20), v(2, 4, 5), v(2, 2, 2)]
39
+ const expectedResult = v(20, 5, 2)
40
+
41
+ expect(divide(...vectors)).toStrictEqual(expectedResult)
42
+ })
43
+
28
44
  test("it should compute the dot product of multiple vectors (aka scalarProduct)", () => {
29
45
  const vectors = [v(1, 2, 3), v(4, 5, 6), v(7, 8, 9)]
30
46
  const expectedResult = 270
@@ -32,6 +48,20 @@ test("it should compute the dot product of multiple vectors (aka scalarProduct)"
32
48
  expect(dot(...vectors)).toStrictEqual(expectedResult)
33
49
  })
34
50
 
51
+ test("it should multiply multiple vectors component-wise (Hadamard product)", () => {
52
+ const vectors = [v(1, 2, 3), v(4, 5, 6), v(2, 2, 2)]
53
+ const expectedResult = v(8, 20, 36)
54
+
55
+ expect(multiply(...vectors)).toStrictEqual(expectedResult)
56
+ })
57
+
58
+ test("it should raise a vector to the power of another vector", () => {
59
+ const vectors = [v(2, 3, 4), v(4, 3, 2)]
60
+ const expectedResult = v(16, 27, 16)
61
+
62
+ expect(power(...vectors)).toStrictEqual(expectedResult)
63
+ })
64
+
35
65
  test("it should subtract multiple vectors", () => {
36
66
  const vectors = [v(1, 2, 3), v(4, 5, 6), v(7, 8, 9)]
37
67
  const expectedResult = v(-10, -11, -12)
@@ -1,26 +1,26 @@
1
- /**
2
- * Represents the input conditions to be evaluated by a decision tree node.
3
- * The `unknown` type is used to allow for flexible condition structures.
4
- */
5
- export type Conditions = unknown
6
-
7
- /**
8
- * Represents the result of a decision tree's `test` function, which is used
9
- * as a key to determine the next branch.
10
- */
11
- export type Outcome = string
12
-
13
- /**
14
- * Represents a node in a decision tree. It consists of:
15
- * - A `test` function that evaluates conditions and returns an outcome.
16
- * - A map of outcomes to subsequent actions, which can be either a final outcome
17
- * or another `DecisionTree` node.
18
- */
19
- export type DecisionTree = {
20
- /**
21
- * A function that takes a set of conditions and returns an outcome string.
22
- * @param conditions - The conditions to evaluate.
23
- * @returns The outcome of the test.
24
- */
25
- test: (conditions: Conditions) => Outcome
26
- } & Record<Outcome, () => Outcome | DecisionTree>
1
+ /**
2
+ * Represents the input conditions to be evaluated by a decision tree node.
3
+ * The `unknown` type is used to allow for flexible condition structures.
4
+ */
5
+ export type Conditions = unknown
6
+
7
+ /**
8
+ * Represents the result of a decision tree's `test` function, which is used
9
+ * as a key to determine the next branch.
10
+ */
11
+ export type Outcome = string
12
+
13
+ /**
14
+ * Represents a node in a decision tree. It consists of:
15
+ * - A `test` function that evaluates conditions and returns an outcome.
16
+ * - A map of outcomes to subsequent actions, which can be either a final outcome
17
+ * or another `DecisionTree` node.
18
+ */
19
+ export type DecisionTree = {
20
+ /**
21
+ * A function that takes a set of conditions and returns an outcome string.
22
+ * @param conditions - The conditions to evaluate.
23
+ * @returns The outcome of the test.
24
+ */
25
+ test: (conditions: Conditions) => Outcome
26
+ } & Record<Outcome, () => Outcome | DecisionTree>
@@ -1,53 +1,53 @@
1
- /**
2
- * Represents a generic tree data structure.
3
- * Each node in the tree has a value and an array of child nodes.
4
- * @template T - The type of the value stored in the tree nodes. Defaults to `any`.
5
- */
6
- export interface Tree<T = any> {
7
- /** The value of the current node. */
8
- value: T
9
- /** An array of child `Tree` nodes. */
10
- children: Tree<T>[]
11
- }
12
-
13
- /**
14
- * A map where keys are node identifiers and values are their [x, y] coordinates.
15
- * Used for efficient node lookups by ID.
16
- */
17
- export interface NodeMap {
18
- [id: string]: [number, number] // [x, y]
19
- }
20
-
21
- /**
22
- * Represents a node in a graph.
23
- */
24
- export interface Node {
25
- /** A unique identifier for the node. */
26
- id: string
27
- /** The [x, y] coordinates of the node. */
28
- position: [number, number] // [x, y]
29
- /** An optional cost associated with traversing to this node. */
30
- cost?: number
31
- }
32
-
33
- /**
34
- * Represents a directed edge (or arc) between two nodes in a graph.
35
- */
36
- export interface Arc {
37
- /** The ID of the starting node. */
38
- from: string
39
- /** The ID of the ending node. */
40
- to: string
41
- /** An optional cost associated with traversing this arc. */
42
- cost?: number
43
- }
44
-
45
- /**
46
- * Represents a graph structure consisting of nodes and arcs.
47
- */
48
- export interface Graph {
49
- /** The nodes of the graph, as either an array or a map for efficient lookups. */
50
- nodes: NodeMap | Node[]
51
- /** An array of arcs connecting the nodes. */
52
- arcs: Arc[]
53
- }
1
+ /**
2
+ * Represents a generic tree data structure.
3
+ * Each node in the tree has a value and an array of child nodes.
4
+ * @template T - The type of the value stored in the tree nodes. Defaults to `any`.
5
+ */
6
+ export interface Tree<T = any> {
7
+ /** The value of the current node. */
8
+ value: T
9
+ /** An array of child `Tree` nodes. */
10
+ children: Tree<T>[]
11
+ }
12
+
13
+ /**
14
+ * A map where keys are node identifiers and values are their [x, y] coordinates.
15
+ * Used for efficient node lookups by ID.
16
+ */
17
+ export interface NodeMap {
18
+ [id: string]: [number, number] // [x, y]
19
+ }
20
+
21
+ /**
22
+ * Represents a node in a graph.
23
+ */
24
+ export interface Node {
25
+ /** A unique identifier for the node. */
26
+ id: string
27
+ /** The [x, y] coordinates of the node. */
28
+ position: [number, number] // [x, y]
29
+ /** An optional cost associated with traversing to this node. */
30
+ cost?: number
31
+ }
32
+
33
+ /**
34
+ * Represents a directed edge (or arc) between two nodes in a graph.
35
+ */
36
+ export interface Arc {
37
+ /** The ID of the starting node. */
38
+ from: string
39
+ /** The ID of the ending node. */
40
+ to: string
41
+ /** An optional cost associated with traversing this arc. */
42
+ cost?: number
43
+ }
44
+
45
+ /**
46
+ * Represents a graph structure consisting of nodes and arcs.
47
+ */
48
+ export interface Graph {
49
+ /** The nodes of the graph, as either an array or a map for efficient lookups. */
50
+ nodes: NodeMap | Node[]
51
+ /** An array of arcs connecting the nodes. */
52
+ arcs: Arc[]
53
+ }
package/types/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export * from "./algorithms"
2
- export * from "./data-structures"
3
- export * from "./math"
4
- export * from "./v"
1
+ export * from "./algorithms"
2
+ export * from "./data-structures"
3
+ export * from "./math"
4
+ export * from "./v"
package/types/math.d.ts CHANGED
@@ -1,90 +1,90 @@
1
- // geometry
2
-
3
- /**
4
- * Represents a point in 3D space using a readonly tuple of numbers.
5
- * @public
6
- */
7
- export type Point = readonly [number, number, number] // [x, y, z]
8
-
9
- /**
10
- * Represents the dimensions of an object in 3D space.
11
- * @public
12
- */
13
- export type Size = readonly [number, number, number] // [width, height, depth]
14
-
15
- /**
16
- * Represents a line in 2D space in the form `ax + by + c = 0`.
17
- * @public
18
- */
19
- export type Line = readonly [number, number, number] // [a, b, c]
20
-
21
- /**
22
- * Represents a circle with a position and radius.
23
- * @public
24
- */
25
- export interface Circle {
26
- /** The center point of the circle. */
27
- position: Point
28
- /** The radius of the circle. */
29
- radius: number
30
- }
31
-
32
- /**
33
- * Represents a rectangle with a position and size.
34
- * @public
35
- */
36
- export interface Rectangle {
37
- /** The top-left corner point of the rectangle. */
38
- position: Point
39
- /** The dimensions of the rectangle. */
40
- size: Size
41
- }
42
-
43
- /**
44
- * Represents a platform, typically for physics or collision detection.
45
- * @public
46
- */
47
- export interface Platform {
48
- /** The position of the platform. */
49
- position: Point
50
- /** The dimensions of the platform. */
51
- size: Size
52
- }
53
-
54
- /**
55
- * Represents a line segment defined by two points.
56
- * @public
57
- */
58
- export interface Segment {
59
- /** The starting point of the segment. */
60
- from: Point
61
- /** The ending point of the segment. */
62
- to: Point
63
- }
64
-
65
- // linear algebra
66
-
67
- /**
68
- * A nominal type brand to identify vector types.
69
- * This prevents accidental assignment of a plain number array to a vector.
70
- * @internal
71
- */
72
- type IsVector = {
73
- readonly __isVector__: true
74
- }
75
-
76
- /** A generic, dynamically-sized vector. */
77
- export type Vector = IsVector & readonly number[]
78
-
79
- /** A 2-dimensional vector. */
80
- export type Vector2 = IsVector & readonly [number, number]
81
-
82
- /** A 3-dimensional vector. */
83
- export type Vector3 = IsVector & readonly [number, number, number]
84
-
85
- /** A 4-dimensional vector, often used for quaternions. */
86
- export type Quaternion = IsVector & readonly [number, number, number, number]
87
-
88
- /** A 7-dimensional vector. */
89
- export type Vector7 = IsVector &
90
- readonly [number, number, number, number, number, number, number]
1
+ // geometry
2
+
3
+ /**
4
+ * Represents a point in 3D space using a readonly tuple of numbers.
5
+ * @public
6
+ */
7
+ export type Point = readonly [number, number, number] // [x, y, z]
8
+
9
+ /**
10
+ * Represents the dimensions of an object in 3D space.
11
+ * @public
12
+ */
13
+ export type Size = readonly [number, number, number] // [width, height, depth]
14
+
15
+ /**
16
+ * Represents a line in 2D space in the form `ax + by + c = 0`.
17
+ * @public
18
+ */
19
+ export type Line = readonly [number, number, number] // [a, b, c]
20
+
21
+ /**
22
+ * Represents a circle with a position and radius.
23
+ * @public
24
+ */
25
+ export interface Circle {
26
+ /** The center point of the circle. */
27
+ position: Point
28
+ /** The radius of the circle. */
29
+ radius: number
30
+ }
31
+
32
+ /**
33
+ * Represents a rectangle with a position and size.
34
+ * @public
35
+ */
36
+ export interface Rectangle {
37
+ /** The top-left corner point of the rectangle. */
38
+ position: Point
39
+ /** The dimensions of the rectangle. */
40
+ size: Size
41
+ }
42
+
43
+ /**
44
+ * Represents a platform, typically for physics or collision detection.
45
+ * @public
46
+ */
47
+ export interface Platform {
48
+ /** The position of the platform. */
49
+ position: Point
50
+ /** The dimensions of the platform. */
51
+ size: Size
52
+ }
53
+
54
+ /**
55
+ * Represents a line segment defined by two points.
56
+ * @public
57
+ */
58
+ export interface Segment {
59
+ /** The starting point of the segment. */
60
+ from: Point
61
+ /** The ending point of the segment. */
62
+ to: Point
63
+ }
64
+
65
+ // linear algebra
66
+
67
+ /**
68
+ * A nominal type brand to identify vector types.
69
+ * This prevents accidental assignment of a plain number array to a vector.
70
+ * @internal
71
+ */
72
+ type IsVector = {
73
+ readonly __isVector__: true
74
+ }
75
+
76
+ /** A generic, dynamically-sized vector. */
77
+ export type Vector = IsVector & readonly number[]
78
+
79
+ /** A 2-dimensional vector. */
80
+ export type Vector2 = IsVector & readonly [number, number]
81
+
82
+ /** A 3-dimensional vector. */
83
+ export type Vector3 = IsVector & readonly [number, number, number]
84
+
85
+ /** A 4-dimensional vector, often used for quaternions. */
86
+ export type Quaternion = IsVector & readonly [number, number, number, number]
87
+
88
+ /** A 7-dimensional vector. */
89
+ export type Vector7 = IsVector &
90
+ readonly [number, number, number, number, number, number, number]
package/types/v.d.ts CHANGED
@@ -1,25 +1,25 @@
1
- import { Vector } from "./math"
2
-
3
- /**
4
- * Ensures that a given value is a vector.
5
- *
6
- * If the value is an array of finite numbers but not already a vector (i.e., it lacks the `__isVector__` property),
7
- * this function converts it into a vector by calling `v()`. If the value is already a vector or not a numeric array,
8
- * it is returned unchanged. This is particularly useful for ensuring that the results of standard array operations
9
- * (like `.map()` or `.filter()`) which return a new array are correctly re-tagged as vectors.
10
- *
11
- * @template T
12
- * @param {T} value The value to check and potentially convert.
13
- * @returns {T extends number[] ? Vector : T} The value as a vector, or the original value if no conversion was needed.
14
- */
15
- export function ensureV<T>(value: T): T extends number[] ? Vector : T
16
-
17
- /**
18
- * A utility function to create a vector from a list of coordinates.
19
- * This is a shorthand for `[x, y, z, ...]`.
20
- * It also tags the array with a non-enumerable `__isVector__` property for
21
- * efficient type checking.
22
- * @param {...number} coords - The coordinates of the vector.
23
- * @returns {Vector} The created vector.
24
- */
25
- export function v(...coords: number[]): Vector
1
+ import { Vector } from "./math"
2
+
3
+ /**
4
+ * Ensures that a given value is a vector.
5
+ *
6
+ * If the value is an array of finite numbers but not already a vector (i.e., it lacks the `__isVector__` property),
7
+ * this function converts it into a vector by calling `v()`. If the value is already a vector or not a numeric array,
8
+ * it is returned unchanged. This is particularly useful for ensuring that the results of standard array operations
9
+ * (like `.map()` or `.filter()`) which return a new array are correctly re-tagged as vectors.
10
+ *
11
+ * @template T
12
+ * @param {T} value The value to check and potentially convert.
13
+ * @returns {T extends number[] ? Vector : T} The value as a vector, or the original value if no conversion was needed.
14
+ */
15
+ export function ensureV<T>(value: T): T extends number[] ? Vector : T
16
+
17
+ /**
18
+ * A utility function to create a vector from a list of coordinates.
19
+ * This is a shorthand for `[x, y, z, ...]`.
20
+ * It also tags the array with a non-enumerable `__isVector__` property for
21
+ * efficient type checking.
22
+ * @param {...number} coords - The coordinates of the vector.
23
+ * @returns {Vector} The created vector.
24
+ */
25
+ export function v(...coords: number[]): Vector