effect 3.14.11 → 3.14.13

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 (49) hide show
  1. package/dist/cjs/BigDecimal.js +3 -0
  2. package/dist/cjs/BigDecimal.js.map +1 -1
  3. package/dist/cjs/BigInt.js +3 -0
  4. package/dist/cjs/BigInt.js.map +1 -1
  5. package/dist/cjs/JSONSchema.js +24 -10
  6. package/dist/cjs/JSONSchema.js.map +1 -1
  7. package/dist/cjs/Number.js +650 -196
  8. package/dist/cjs/Number.js.map +1 -1
  9. package/dist/cjs/ParseResult.js +3 -1
  10. package/dist/cjs/ParseResult.js.map +1 -1
  11. package/dist/cjs/Schema.js +4 -2
  12. package/dist/cjs/Schema.js.map +1 -1
  13. package/dist/cjs/internal/version.js +1 -1
  14. package/dist/dts/BigDecimal.d.ts +3 -0
  15. package/dist/dts/BigDecimal.d.ts.map +1 -1
  16. package/dist/dts/BigInt.d.ts +3 -0
  17. package/dist/dts/BigInt.d.ts.map +1 -1
  18. package/dist/dts/JSONSchema.d.ts.map +1 -1
  19. package/dist/dts/Number.d.ts +866 -421
  20. package/dist/dts/Number.d.ts.map +1 -1
  21. package/dist/dts/ParseResult.d.ts.map +1 -1
  22. package/dist/dts/Schema.d.ts +1 -3
  23. package/dist/dts/Schema.d.ts.map +1 -1
  24. package/dist/dts/index.d.ts +98 -3
  25. package/dist/dts/index.d.ts.map +1 -1
  26. package/dist/esm/BigDecimal.js +3 -0
  27. package/dist/esm/BigDecimal.js.map +1 -1
  28. package/dist/esm/BigInt.js +3 -0
  29. package/dist/esm/BigInt.js.map +1 -1
  30. package/dist/esm/JSONSchema.js +24 -10
  31. package/dist/esm/JSONSchema.js.map +1 -1
  32. package/dist/esm/Number.js +645 -192
  33. package/dist/esm/Number.js.map +1 -1
  34. package/dist/esm/ParseResult.js +2 -1
  35. package/dist/esm/ParseResult.js.map +1 -1
  36. package/dist/esm/Schema.js +4 -2
  37. package/dist/esm/Schema.js.map +1 -1
  38. package/dist/esm/index.js +98 -3
  39. package/dist/esm/index.js.map +1 -1
  40. package/dist/esm/internal/version.js +1 -1
  41. package/package.json +1 -1
  42. package/src/BigDecimal.ts +3 -0
  43. package/src/BigInt.ts +3 -0
  44. package/src/JSONSchema.ts +20 -7
  45. package/src/Number.ts +913 -475
  46. package/src/ParseResult.ts +2 -1
  47. package/src/Schema.ts +11 -8
  48. package/src/index.ts +98 -3
  49. package/src/internal/version.ts +1 -1
@@ -1,246 +1,728 @@
1
1
  /**
2
- * This module provides utility functions and type class instances for working with the `number` type in TypeScript.
3
- * It includes functions for basic arithmetic operations, as well as type class instances for
4
- * `Equivalence` and `Order`.
2
+ * # Number
3
+ *
4
+ * This module provides utility functions and type class instances for working
5
+ * with the `number` type in TypeScript. It includes functions for basic
6
+ * arithmetic operations, as well as type class instances for `Equivalence` and
7
+ * `Order`.
8
+ *
9
+ * ## Operations Reference
10
+ *
11
+ * | Category | Operation | Description | Domain | Co-domain |
12
+ * | ------------ | ------------------------------------------ | ------------------------------------------------------- | ------------------------------ | --------------------- |
13
+ * | constructors | {@link module:Number.parse} | Safely parses a string to a number | `string` | `Option<number>` |
14
+ * | | | | | |
15
+ * | math | {@link module:Number.sum} | Adds two numbers | `number`, `number` | `number` |
16
+ * | math | {@link module:Number.sumAll} | Sums all numbers in a collection | `Iterable<number>` | `number` |
17
+ * | math | {@link module:Number.subtract} | Subtracts one number from another | `number`, `number` | `number` |
18
+ * | math | {@link module:Number.multiply} | Multiplies two numbers | `number`, `number` | `number` |
19
+ * | math | {@link module:Number.multiplyAll} | Multiplies all numbers in a collection | `Iterable<number>` | `number` |
20
+ * | math | {@link module:Number.divide} | Safely divides handling division by zero | `number`, `number` | `Option<number>` |
21
+ * | math | {@link module:Number.unsafeDivide} | Divides but misbehaves for division by zero | `number`, `number` | `number` |
22
+ * | math | {@link module:Number.remainder} | Calculates remainder of division | `number`, `number` | `number` |
23
+ * | math | {@link module:Number.increment} | Adds 1 to a number | `number` | `number` |
24
+ * | math | {@link module:Number.decrement} | Subtracts 1 from a number | `number` | `number` |
25
+ * | math | {@link module:Number.sign} | Determines the sign of a number | `number` | `Ordering` |
26
+ * | math | {@link module:Number.nextPow2} | Finds the next power of 2 | `number` | `number` |
27
+ * | math | {@link module:Number.round} | Rounds a number with specified precision | `number`, `number` | `number` |
28
+ * | | | | | |
29
+ * | predicates | {@link module:Number.between} | Checks if a number is in a range | `number`, `{minimum, maximum}` | `boolean` |
30
+ * | predicates | {@link module:Number.lessThan} | Checks if one number is less than another | `number`, `number` | `boolean` |
31
+ * | predicates | {@link module:Number.lessThanOrEqualTo} | Checks if one number is less than or equal | `number`, `number` | `boolean` |
32
+ * | predicates | {@link module:Number.greaterThan} | Checks if one number is greater than another | `number`, `number` | `boolean` |
33
+ * | predicates | {@link module:Number.greaterThanOrEqualTo} | Checks if one number is greater or equal | `number`, `number` | `boolean` |
34
+ * | | | | | |
35
+ * | guards | {@link module:Number.isNumber} | Type guard for JavaScript numbers | `unknown` | `boolean` |
36
+ * | | | | | |
37
+ * | comparison | {@link module:Number.min} | Returns the minimum of two numbers | `number`, `number` | `number` |
38
+ * | comparison | {@link module:Number.max} | Returns the maximum of two numbers | `number`, `number` | `number` |
39
+ * | comparison | {@link module:Number.clamp} | Restricts a number to a range | `number`, `{minimum, maximum}` | `number` |
40
+ * | | | | | |
41
+ * | instances | {@link module:Number.Equivalence} | Equivalence instance for numbers | | `Equivalence<number>` |
42
+ * | instances | {@link module:Number.Order} | Order instance for numbers | | `Order<number>` |
43
+ * | | | | | |
44
+ * | errors | {@link module:Number.DivisionByZeroError} | Error thrown by unsafeDivide | | |
45
+ *
46
+ * ## Composition Patterns and Type Safety
47
+ *
48
+ * When building function pipelines, understanding how types flow through
49
+ * operations is critical:
50
+ *
51
+ * ### Composing with type-preserving operations
52
+ *
53
+ * Most operations in this module are type-preserving (`number → number`),
54
+ * making them easily composable in pipelines:
5
55
  *
56
+ * ```ts
57
+ * import { pipe } from "effect"
58
+ * import * as Number from "effect/Number"
59
+ *
60
+ * const result = pipe(
61
+ * 10,
62
+ * Number.increment, // number → number
63
+ * Number.multiply(2), // number → number
64
+ * Number.round(1) // number → number
65
+ * ) // Result: number (21)
66
+ * ```
67
+ *
68
+ * ### Working with Option results
69
+ *
70
+ * Operations that might fail (like division by zero) return Option types and
71
+ * require Option combinators:
72
+ *
73
+ * ```ts
74
+ * import { pipe, Option } from "effect"
75
+ * import * as Number from "effect/Number"
76
+ *
77
+ * const result = pipe(
78
+ * 10,
79
+ * Number.divide(0), // number → Option<number>
80
+ * Option.getOrElse(() => 0) // Option<number> → number
81
+ * ) // Result: number (0)
82
+ * ```
83
+ *
84
+ * ### Composition best practices
85
+ *
86
+ * - Chain type-preserving operations for maximum composability
87
+ * - Use Option combinators when working with potentially failing operations
88
+ * - Consider using Effect for operations that might fail with specific errors
89
+ * - Remember that all operations maintain JavaScript's floating-point precision
90
+ * limitations
91
+ *
92
+ * @module Number
6
93
  * @since 2.0.0
94
+ * @see {@link module:BigInt} for more similar operations on `bigint` types
95
+ * @see {@link module:BigDecimal} for more similar operations on `BigDecimal` types
7
96
  */
8
97
  import * as equivalence from "./Equivalence.js";
9
98
  import { dual } from "./Function.js";
10
99
  import * as option from "./internal/option.js";
100
+ import * as _Iterable from "./Iterable.js";
11
101
  import * as order from "./Order.js";
12
102
  import * as predicate from "./Predicate.js";
13
103
  /**
14
- * Tests if a value is a `number`.
104
+ * Type guard that tests if a value is a member of the set of JavaScript
105
+ * numbers.
15
106
  *
107
+ * @memberof Number
108
+ * @since 2.0.0
109
+ * @category guards
16
110
  * @example
17
- * ```ts
18
- * import * as assert from "node:assert"
19
- * import { isNumber } from "effect/Number"
20
111
  *
21
- * assert.deepStrictEqual(isNumber(2), true)
22
- * assert.deepStrictEqual(isNumber("2"), false)
112
+ * ```ts
113
+ * import * as assert from "node:assert/strict"
114
+ * import * as Number from "effect/Number"
115
+ *
116
+ * // Regular numbers
117
+ * assert.equal(Number.isNumber(2), true)
118
+ * assert.equal(Number.isNumber(-3.14), true)
119
+ * assert.equal(Number.isNumber(0), true)
120
+ *
121
+ * // Special numeric values
122
+ * assert.equal(Number.isNumber(Infinity), true)
123
+ * assert.equal(Number.isNumber(NaN), true)
124
+ *
125
+ * // Non-number values
126
+ * assert.equal(Number.isNumber("2"), false)
127
+ * assert.equal(Number.isNumber(true), false)
128
+ * assert.equal(Number.isNumber(null), false)
129
+ * assert.equal(Number.isNumber(undefined), false)
130
+ * assert.equal(Number.isNumber({}), false)
131
+ * assert.equal(Number.isNumber([]), false)
132
+ *
133
+ * // Using as a type guard in conditionals
134
+ * function processValue(value: unknown): string {
135
+ * if (Number.isNumber(value)) {
136
+ * // TypeScript now knows 'value' is a number
137
+ * return `Numeric value: ${value.toFixed(2)}`
138
+ * }
139
+ * return "Not a number"
140
+ * }
141
+ *
142
+ * assert.strictEqual(processValue(42), "Numeric value: 42.00")
143
+ * assert.strictEqual(processValue("hello"), "Not a number")
144
+ *
145
+ * // Filtering for numbers in an array
146
+ * const mixed = [1, "two", 3, false, 5]
147
+ * const onlyNumbers = mixed.filter(Number.isNumber)
148
+ * assert.equal(onlyNumbers, [1, 3, 5])
23
149
  * ```
24
150
  *
25
- * @category guards
26
- * @since 2.0.0
151
+ * @param input - The value to test for membership in the set of JavaScript
152
+ * numbers
153
+ *
154
+ * @returns `true` if the input is a JavaScript number, `false` otherwise
27
155
  */
28
156
  export const isNumber = predicate.isNumber;
29
157
  /**
30
- * Provides an addition operation on `number`s.
158
+ * Returns the additive inverse of a number, effectively negating it.
31
159
  *
160
+ * @memberof Number
161
+ * @since 3.14.6
32
162
  * @example
33
- * ```ts
34
- * import * as assert from "node:assert"
35
- * import { sum } from "effect/Number"
36
163
  *
37
- * assert.deepStrictEqual(sum(2, 3), 5)
164
+ * ```ts
165
+ * import * as assert from "node:assert/strict"
166
+ * import { pipe } from "effect"
167
+ * import * as Number from "effect/Number"
168
+ *
169
+ * assert.equal(
170
+ * Number.negate(5), //
171
+ * -5
172
+ * )
173
+ *
174
+ * assert.equal(
175
+ * Number.negate(-5), //
176
+ * 5
177
+ * )
178
+ *
179
+ * assert.equal(
180
+ * Number.negate(0), //
181
+ * 0
182
+ * )
38
183
  * ```
39
184
  *
40
- * @category math
185
+ * @param n - The number value to be negated.
186
+ *
187
+ * @returns The negated number value.
188
+ */
189
+ export const negate = n => multiply(n, -1);
190
+ /**
191
+ * Performs addition in the set of JavaScript numbers.
192
+ *
193
+ * @memberof Number
41
194
  * @since 2.0.0
195
+ * @category math
196
+ * @example
197
+ *
198
+ * ```ts
199
+ * import * as assert from "node:assert/strict"
200
+ * import { pipe } from "effect"
201
+ * import * as Number from "effect/Number"
202
+ *
203
+ * // Data-first style (direct application)
204
+ * assert.equal(Number.sum(2, 3), 5)
205
+ * assert.equal(Number.sum(-10, 5), -5)
206
+ * assert.equal(Number.sum(0.1, 0.2), 0.30000000000000004) // Note: floating-point precision limitation
207
+ *
208
+ * // Data-last style (pipeable)
209
+ * assert.equal(
210
+ * pipe(
211
+ * 10,
212
+ * Number.sum(5) // 10 + 5 = 15
213
+ * ),
214
+ * 15
215
+ * )
216
+ *
217
+ * // Chaining multiple additions
218
+ * assert.equal(
219
+ * pipe(
220
+ * 1,
221
+ * Number.sum(2), // 1 + 2 = 3
222
+ * Number.sum(3), // 3 + 3 = 6
223
+ * Number.sum(4) // 6 + 4 = 10
224
+ * ),
225
+ * 10
226
+ * )
227
+ *
228
+ * // Identity property: a + 0 = a
229
+ * assert.equal(Number.sum(42, 0), 42)
230
+ *
231
+ * // Commutative property: a + b = b + a
232
+ * assert.equal(Number.sum(5, 3), Number.sum(3, 5))
233
+ * ```
42
234
  */
43
235
  export const sum = /*#__PURE__*/dual(2, (self, that) => self + that);
44
236
  /**
45
- * Provides a multiplication operation on `number`s.
237
+ * Computes the sum of all elements in an iterable collection of numbers.
46
238
  *
239
+ * @memberof Number
240
+ * @since 2.0.0
241
+ * @category math
47
242
  * @example
243
+ *
48
244
  * ```ts
49
- * import * as assert from "node:assert"
50
- * import { multiply } from "effect/Number"
245
+ * import * as assert from "node:assert/strict"
246
+ * import * as Number from "effect/Number"
247
+ *
248
+ * // Basic sums
249
+ * assert.equal(Number.sumAll([2, 3, 4]), 9) // 2 + 3 + 4 = 9
250
+ * assert.equal(Number.sumAll([1.1, 2.2, 3.3]), 6.6) // 1.1 + 2.2 + 3.3 = 6.6
251
+ *
252
+ * // Empty collection returns the additive identity (0)
253
+ * assert.equal(Number.sumAll([]), 0)
254
+ *
255
+ * // Single element collection
256
+ * assert.equal(Number.sumAll([42]), 42)
257
+ *
258
+ * // Sums with negative numbers
259
+ * assert.equal(Number.sumAll([2, -3, 4]), 3) // 2 + (-3) + 4 = 3
260
+ * assert.equal(Number.sumAll([-2, -3, -4]), -9) // (-2) + (-3) + (-4) = -9
261
+ *
262
+ * // Works with any iterable
263
+ * assert.equal(Number.sumAll(new Set([2, 3, 4])), 9)
264
+ *
265
+ * // Using with generated sequences
266
+ * function* range(start: number, end: number) {
267
+ * for (let i = start; i <= end; i++) yield i
268
+ * }
269
+ *
270
+ * // Compute sum of first 5 natural numbers: 1 + 2 + 3 + 4 + 5 = 15
271
+ * assert.equal(Number.sumAll(range(1, 5)), 15)
51
272
  *
52
- * assert.deepStrictEqual(multiply(2, 3), 6)
273
+ * // Floating point precision example
274
+ * assert.equal(
275
+ * Number.sumAll([0.1, 0.2]),
276
+ * 0.30000000000000004 // Note IEEE 754 precision limitation
277
+ * )
53
278
  * ```
54
279
  *
55
- * @category math
56
- * @since 2.0.0
280
+ * @param collection - An `iterable` containing the `numbers` to sum
281
+ *
282
+ * @returns The sum of all numbers in the collection, or 0 if the collection is
283
+ * empty
57
284
  */
58
- export const multiply = /*#__PURE__*/dual(2, (self, that) => self * that);
285
+ export const sumAll = collection => _Iterable.reduce(collection, 0, sum);
59
286
  /**
60
- * Provides a subtraction operation on `number`s.
287
+ * Performs subtraction in the set of JavaScript numbers.
61
288
  *
289
+ * @memberof Number
290
+ * @since 2.0.0
291
+ * @category math
62
292
  * @example
63
- * ```ts
64
- * import * as assert from "node:assert"
65
- * import { subtract } from "effect/Number"
66
293
  *
67
- * assert.deepStrictEqual(subtract(2, 3), -1)
294
+ * ```ts
295
+ * import * as assert from "node:assert/strict"
296
+ * import { pipe } from "effect"
297
+ * import * as Number from "effect/Number"
298
+ *
299
+ * // Data-first style (direct application)
300
+ * assert.equal(Number.subtract(2, 3), -1) // 2 - 3 = -1
301
+ * assert.equal(Number.subtract(10, 5), 5) // 10 - 5 = 5
302
+ * assert.equal(Number.subtract(0.3, 0.1), 0.19999999999999998) // Note: floating-point precision limitation
303
+ *
304
+ * // Data-last style (pipeable)
305
+ * assert.equal(
306
+ * pipe(
307
+ * 10,
308
+ * Number.subtract(5) // 10 - 5 = 5
309
+ * ),
310
+ * 5
311
+ * )
312
+ *
313
+ * // Chaining multiple subtractions
314
+ * assert.equal(
315
+ * pipe(
316
+ * 20,
317
+ * Number.subtract(5), // 20 - 5 = 15
318
+ * Number.subtract(3), // 15 - 3 = 12
319
+ * Number.subtract(2) // 12 - 2 = 10
320
+ * ),
321
+ * 10
322
+ * )
323
+ *
324
+ * // Right identity property: a - 0 = a
325
+ * assert.equal(Number.subtract(42, 0), 42)
326
+ *
327
+ * // Self-annihilation property: a - a = 0
328
+ * assert.equal(Number.subtract(42, 42), 0)
329
+ *
330
+ * // Non-commutative property: a - b ≠ b - a
331
+ * assert.equal(Number.subtract(5, 3), 2) // 5 - 3 = 2
332
+ * assert.equal(Number.subtract(3, 5), -2) // 3 - 5 = -2
333
+ *
334
+ * // Inverse relation: a - b = -(b - a)
335
+ * assert.equal(Number.subtract(5, 3), -Number.subtract(3, 5))
68
336
  * ```
337
+ */
338
+ export const subtract = /*#__PURE__*/dual(2, (minuend, subtrahend) => minuend - subtrahend);
339
+ /**
340
+ * Performs **multiplication** in the set of JavaScript numbers.
69
341
  *
70
- * @category math
342
+ * @memberof Number
71
343
  * @since 2.0.0
344
+ * @category math
345
+ * @example
346
+ *
347
+ * ```ts
348
+ * import * as assert from "node:assert/strict"
349
+ * import { pipe } from "effect"
350
+ * import * as Number from "effect/Number"
351
+ *
352
+ * // Data-first style (direct application)
353
+ * assert.equal(Number.multiply(2, 3), 6) // 2 × 3 = 6
354
+ * assert.equal(Number.multiply(-4, 5), -20) // (-4) × 5 = -20
355
+ * assert.equal(Number.multiply(-3, -2), 6) // (-3) × (-2) = 6
356
+ * assert.equal(Number.multiply(0.1, 0.2), 0.020000000000000004) // Note: floating-point precision limitation
357
+ *
358
+ * // Data-last style (pipeable)
359
+ * assert.equal(
360
+ * pipe(
361
+ * 10,
362
+ * Number.multiply(5) // 10 × 5 = 50
363
+ * ),
364
+ * 50
365
+ * )
366
+ *
367
+ * // Chaining multiple multiplications
368
+ * assert.equal(
369
+ * pipe(
370
+ * 2,
371
+ * Number.multiply(3), // 2 × 3 = 6
372
+ * Number.multiply(4), // 6 × 4 = 24
373
+ * Number.multiply(0.5) // 24 × 0.5 = 12
374
+ * ),
375
+ * 12
376
+ * )
377
+ *
378
+ * // Identity property: a × 1 = a
379
+ * assert.equal(Number.multiply(42, 1), 42)
380
+ *
381
+ * // Zero property: a × 0 = 0
382
+ * assert.equal(Number.multiply(42, 0), 0)
383
+ *
384
+ * // Commutative property: a × b = b × a
385
+ * assert.equal(Number.multiply(5, 3), Number.multiply(3, 5))
386
+ *
387
+ * // Associative property: (a × b) × c = a × (b × c)
388
+ * const a = 2,
389
+ * b = 3,
390
+ * c = 4
391
+ * assert.equal(
392
+ * Number.multiply(Number.multiply(a, b), c),
393
+ * Number.multiply(a, Number.multiply(b, c))
394
+ * )
395
+ * ```
72
396
  */
73
- export const subtract = /*#__PURE__*/dual(2, (self, that) => self - that);
397
+ export const multiply = /*#__PURE__*/dual(2, (multiplier, multiplicand) => multiplier * multiplicand);
74
398
  /**
75
- * Provides a division operation on `number`s.
399
+ * Computes the product of all elements in an iterable collection of numbers.
76
400
  *
401
+ * @memberof Number
402
+ * @since 2.0.0
403
+ * @category math
77
404
  * @example
405
+ *
78
406
  * ```ts
79
- * import * as assert from "node:assert"
80
- * import { Number, Option } from "effect"
407
+ * import * as assert from "node:assert/strict"
408
+ * import * as Number from "effect/Number"
409
+ *
410
+ * // Basic products
411
+ * assert.equal(Number.multiplyAll([2, 3, 4]), 24) // 2 × 3 × 4 = 24
412
+ * assert.equal(Number.multiplyAll([1.5, 2, 3]), 9) // 1.5 × 2 × 3 = 9
413
+ *
414
+ * // Empty collection returns the multiplicative identity (1)
415
+ * assert.equal(Number.multiplyAll([]), 1)
81
416
  *
82
- * assert.deepStrictEqual(Number.divide(6, 3), Option.some(2))
83
- * assert.deepStrictEqual(Number.divide(6, 0), Option.none())
417
+ * // Single element collection
418
+ * assert.equal(Number.multiplyAll([42]), 42)
419
+ *
420
+ * // Products with negative numbers
421
+ * assert.equal(Number.multiplyAll([2, -3, 4]), -24) // 2 × (-3) × 4 = -24
422
+ * assert.equal(Number.multiplyAll([-2, -3]), 6) // (-2) × (-3) = 6
423
+ *
424
+ * // Zero property - if any element is zero, product is zero
425
+ * assert.equal(Number.multiplyAll([2, 0, 3]), 0)
426
+ *
427
+ * // Works with any iterable
428
+ * assert.equal(Number.multiplyAll(new Set([2, 3, 4])), 24)
429
+ *
430
+ * // Using with generated sequences
431
+ * function* range(start: number, end: number) {
432
+ * for (let i = start; i <= end; i++) yield i
433
+ * }
434
+ *
435
+ * // Compute factorial: 5! = 5 × 4 × 3 × 2 × 1 = 120
436
+ * assert.equal(Number.multiplyAll(range(1, 5)), 120)
84
437
  * ```
85
438
  *
86
- * @category math
439
+ * @param collection - An `iterable` containing the `numbers` to multiply
440
+ *
441
+ * @returns The product of all numbers in the collection, or 1 if the collection
442
+ * is empty
443
+ */
444
+ export const multiplyAll = collection => {
445
+ let out = 1;
446
+ for (const n of collection) {
447
+ if (n === 0) {
448
+ return 0;
449
+ }
450
+ out *= n;
451
+ }
452
+ return out;
453
+ };
454
+ /**
455
+ * Performs division in the set of JavaScript numbers, returning the result
456
+ * wrapped in an `Option` to handle division by zero.
457
+ *
458
+ * @memberof Number
87
459
  * @since 2.0.0
460
+ * @category math
461
+ * @example
462
+ *
463
+ * ```ts
464
+ * import * as assert from "node:assert/strict"
465
+ * import { pipe, Option } from "effect"
466
+ * import * as Number from "effect/Number"
467
+ *
468
+ * // Data-first style (direct application)
469
+ * assert.equal(Number.divide(6, 3), Option.some(2)) // 6 ÷ 3 = 2
470
+ * assert.equal(Number.divide(-8, 4), Option.some(-2)) // (-8) ÷ 4 = -2
471
+ * assert.equal(Number.divide(-10, -5), Option.some(2)) // (-10) ÷ (-5) = 2
472
+ * assert.equal(Number.divide(1, 3), Option.some(0.3333333333333333)) // Note: floating-point approximation
473
+ *
474
+ * // Handling division by zero
475
+ * assert.equal(Number.divide(6, 0), Option.none()) // 6 ÷ 0 is undefined
476
+ *
477
+ * // Data-last style (pipeable)
478
+ * assert.equal(
479
+ * pipe(
480
+ * 10,
481
+ * Number.divide(2) // 10 ÷ 2 = 5
482
+ * ),
483
+ * Option.some(5)
484
+ * )
485
+ *
486
+ * // Chaining multiple divisions using Option combinators
487
+ * assert.equal(
488
+ * pipe(
489
+ * Option.some(24),
490
+ * Option.flatMap((n) => Number.divide(n, 2)), // 24 ÷ 2 = 12
491
+ * Option.flatMap(Number.divide(3)), // 12 ÷ 3 = 4
492
+ * Option.flatMap(Number.divide(2)) // 4 ÷ 2 = 2
493
+ * ),
494
+ * Option.some(2)
495
+ * )
496
+ *
497
+ * // Division-by-one property: a ÷ 1 = a
498
+ * assert.equal(Number.divide(42, 1), Option.some(42))
499
+ *
500
+ * // Self-division property: a ÷ a = 1 (for a ≠ 0)
501
+ * assert.equal(Number.divide(42, 42), Option.some(1))
502
+ *
503
+ * // Non-commutative property: a ÷ b ≠ b ÷ a
504
+ * assert.notDeepStrictEqual(
505
+ * Number.divide(6, 3), // 6 ÷ 3 = 2
506
+ * Number.divide(3, 6) // 3 ÷ 6 = 0.5
507
+ * )
508
+ * ```
88
509
  */
89
- export const divide = /*#__PURE__*/dual(2, (self, that) => that === 0 ? option.none : option.some(self / that));
510
+ export const divide = /*#__PURE__*/dual(2, (dividend, divisor) => divisor === 0 ? option.none : option.some(dividend / divisor));
90
511
  /**
91
- * Provides a division operation on `number`s.
512
+ * Performs division in the set of JavaScript numbers, but misbehaves for
513
+ * division by zero.
514
+ *
515
+ * Unlike {@link module:Number.divide} which returns an Option, this function
516
+ * directly returns a number or `Infinity` or `NaN`.
92
517
  *
93
- * Throws a `RangeError` if the divisor is `0`.
518
+ * - If the `divisor` is zero, it returns `Infinity`.
519
+ * - If both the `dividend` and the `divisor` are zero, then it returns `NaN`.
94
520
  *
521
+ * @memberof Number
522
+ * @since 2.0.0
523
+ * @category math
95
524
  * @example
96
- * ```ts
97
- * import * as assert from "node:assert"
98
- * import { unsafeDivide } from "effect/Number"
99
525
  *
100
- * assert.deepStrictEqual(unsafeDivide(6, 3), 2)
526
+ * ```ts
527
+ * import * as assert from "node:assert/strict"
528
+ * import { pipe } from "effect"
529
+ * import * as Number from "effect/Number"
530
+ *
531
+ * // Data-first style (direct application)
532
+ * assert.equal(Number.unsafeDivide(6, 3), 2) // 6 ÷ 3 = 2
533
+ * assert.equal(Number.unsafeDivide(-8, 4), -2) // (-8) ÷ 4 = -2
534
+ * assert.equal(Number.unsafeDivide(-10, -5), 2) // (-10) ÷ (-5) = 2
535
+ * assert.equal(Number.unsafeDivide(1, 3), 0.3333333333333333)
536
+ *
537
+ * // Data-last style (pipeable)
538
+ * assert.equal(
539
+ * pipe(
540
+ * 10,
541
+ * Number.unsafeDivide(2) // 10 ÷ 2 = 5
542
+ * ),
543
+ * 5
544
+ * )
545
+ *
546
+ * // Chaining multiple divisions
547
+ * assert.equal(
548
+ * pipe(
549
+ * 24,
550
+ * Number.unsafeDivide(2), // 24 ÷ 2 = 12
551
+ * Number.unsafeDivide(3), // 12 ÷ 3 = 4
552
+ * Number.unsafeDivide(2) // 4 ÷ 2 = 2
553
+ * ),
554
+ * 2
555
+ * )
556
+ *
557
+ * assert.equal(Number.unsafeDivide(6, 0), Infinity)
558
+ *
559
+ * assert.equal(Number.unsafeDivide(0, 0), NaN)
560
+ *
561
+ * // Compare with safe division
562
+ * const safeResult = Number.divide(6, 3) // Option.some(2)
563
+ * const unsafeResult = Number.unsafeDivide(6, 3) // 2 directly
101
564
  * ```
102
565
  *
103
- * @category math
104
- * @since 2.0.0
566
+ * @throws - An {@link module:Number.DivisionByZeroError} if the divisor is zero.
567
+ * @see {@link module:Number.divide} - Safe division returning an Option
105
568
  */
106
- export const unsafeDivide = /*#__PURE__*/dual(2, (self, that) => self / that);
569
+ export const unsafeDivide = /*#__PURE__*/dual(2, (dividend, divisor) => dividend / divisor);
107
570
  /**
108
571
  * Returns the result of adding `1` to a given number.
109
572
  *
573
+ * @memberof Number
574
+ * @since 2.0.0
575
+ * @category math
110
576
  * @example
577
+ *
111
578
  * ```ts
112
- * import * as assert from "node:assert"
579
+ * import * as assert from "node:assert/strict"
113
580
  * import { increment } from "effect/Number"
114
581
  *
115
- * assert.deepStrictEqual(increment(2), 3)
582
+ * assert.equal(increment(2), 3)
116
583
  * ```
117
- *
118
- * @category math
119
- * @since 2.0.0
120
584
  */
121
- export const increment = n => n + 1;
585
+ export const increment = n => sum(n, 1);
122
586
  /**
123
587
  * Decrements a number by `1`.
124
588
  *
589
+ * @memberof Number
590
+ * @since 2.0.0
591
+ * @category math
125
592
  * @example
593
+ *
126
594
  * ```ts
127
- * import * as assert from "node:assert"
595
+ * import * as assert from "node:assert/strict"
128
596
  * import { decrement } from "effect/Number"
129
597
  *
130
- * assert.deepStrictEqual(decrement(3), 2)
598
+ * assert.equal(decrement(3), 2)
131
599
  * ```
132
- *
133
- * @category math
134
- * @since 2.0.0
135
600
  */
136
- export const decrement = n => n - 1;
601
+ export const decrement = n => subtract(n, 1);
137
602
  /**
138
- * @category instances
603
+ * @memberof Number
139
604
  * @since 2.0.0
605
+ * @category instances
140
606
  */
141
607
  export const Equivalence = equivalence.number;
142
608
  /**
143
- * @category instances
609
+ * @memberof Number
144
610
  * @since 2.0.0
611
+ * @category instances
145
612
  */
146
613
  export const Order = order.number;
147
614
  /**
148
- * Returns `true` if the first argument is less than the second, otherwise `false`.
615
+ * Returns `true` if the first argument is less than the second, otherwise
616
+ * `false`.
149
617
  *
618
+ * @memberof Number
619
+ * @since 2.0.0
620
+ * @category predicates
150
621
  * @example
622
+ *
151
623
  * ```ts
152
- * import * as assert from "node:assert"
624
+ * import * as assert from "node:assert/strict"
153
625
  * import { lessThan } from "effect/Number"
154
626
  *
155
- * assert.deepStrictEqual(lessThan(2, 3), true)
156
- * assert.deepStrictEqual(lessThan(3, 3), false)
157
- * assert.deepStrictEqual(lessThan(4, 3), false)
627
+ * assert.equal(lessThan(2, 3), true)
628
+ * assert.equal(lessThan(3, 3), false)
629
+ * assert.equal(lessThan(4, 3), false)
158
630
  * ```
159
- *
160
- * @category predicates
161
- * @since 2.0.0
162
631
  */
163
632
  export const lessThan = /*#__PURE__*/order.lessThan(Order);
164
633
  /**
165
- * Returns a function that checks if a given `number` is less than or equal to the provided one.
634
+ * Returns a function that checks if a given `number` is less than or equal to
635
+ * the provided one.
166
636
  *
637
+ * @memberof Number
638
+ * @since 2.0.0
639
+ * @category predicates
167
640
  * @example
641
+ *
168
642
  * ```ts
169
- * import * as assert from "node:assert"
643
+ * import * as assert from "node:assert/strict"
170
644
  * import { lessThanOrEqualTo } from "effect/Number"
171
645
  *
172
- * assert.deepStrictEqual(lessThanOrEqualTo(2, 3), true)
173
- * assert.deepStrictEqual(lessThanOrEqualTo(3, 3), true)
174
- * assert.deepStrictEqual(lessThanOrEqualTo(4, 3), false)
646
+ * assert.equal(lessThanOrEqualTo(2, 3), true)
647
+ * assert.equal(lessThanOrEqualTo(3, 3), true)
648
+ * assert.equal(lessThanOrEqualTo(4, 3), false)
175
649
  * ```
176
- *
177
- * @category predicates
178
- * @since 2.0.0
179
650
  */
180
651
  export const lessThanOrEqualTo = /*#__PURE__*/order.lessThanOrEqualTo(Order);
181
652
  /**
182
- * Returns `true` if the first argument is greater than the second, otherwise `false`.
653
+ * Returns `true` if the first argument is greater than the second, otherwise
654
+ * `false`.
183
655
  *
656
+ * @memberof Number
657
+ * @since 2.0.0
658
+ * @category predicates
184
659
  * @example
660
+ *
185
661
  * ```ts
186
- * import * as assert from "node:assert"
662
+ * import * as assert from "node:assert/strict"
187
663
  * import { greaterThan } from "effect/Number"
188
664
  *
189
- * assert.deepStrictEqual(greaterThan(2, 3), false)
190
- * assert.deepStrictEqual(greaterThan(3, 3), false)
191
- * assert.deepStrictEqual(greaterThan(4, 3), true)
665
+ * assert.equal(greaterThan(2, 3), false)
666
+ * assert.equal(greaterThan(3, 3), false)
667
+ * assert.equal(greaterThan(4, 3), true)
192
668
  * ```
193
- *
194
- * @category predicates
195
- * @since 2.0.0
196
669
  */
197
670
  export const greaterThan = /*#__PURE__*/order.greaterThan(Order);
198
671
  /**
199
- * Returns a function that checks if a given `number` is greater than or equal to the provided one.
672
+ * Returns a function that checks if a given `number` is greater than or equal
673
+ * to the provided one.
200
674
  *
675
+ * @memberof Number
676
+ * @since 2.0.0
677
+ * @category predicates
201
678
  * @example
679
+ *
202
680
  * ```ts
203
- * import * as assert from "node:assert"
681
+ * import * as assert from "node:assert/strict"
204
682
  * import { greaterThanOrEqualTo } from "effect/Number"
205
683
  *
206
- * assert.deepStrictEqual(greaterThanOrEqualTo(2, 3), false)
207
- * assert.deepStrictEqual(greaterThanOrEqualTo(3, 3), true)
208
- * assert.deepStrictEqual(greaterThanOrEqualTo(4, 3), true)
684
+ * assert.equal(greaterThanOrEqualTo(2, 3), false)
685
+ * assert.equal(greaterThanOrEqualTo(3, 3), true)
686
+ * assert.equal(greaterThanOrEqualTo(4, 3), true)
209
687
  * ```
210
- *
211
- * @category predicates
212
- * @since 2.0.0
213
688
  */
214
689
  export const greaterThanOrEqualTo = /*#__PURE__*/order.greaterThanOrEqualTo(Order);
215
690
  /**
216
691
  * Checks if a `number` is between a `minimum` and `maximum` value (inclusive).
217
692
  *
693
+ * @memberof Number
694
+ * @since 2.0.0
695
+ * @category predicates
218
696
  * @example
697
+ *
219
698
  * ```ts
220
- * import * as assert from "node:assert"
699
+ * import * as assert from "node:assert/strict"
221
700
  * import { Number } from "effect"
222
701
  *
223
702
  * const between = Number.between({ minimum: 0, maximum: 5 })
224
703
  *
225
- * assert.deepStrictEqual(between(3), true)
226
- * assert.deepStrictEqual(between(-1), false)
227
- * assert.deepStrictEqual(between(6), false)
704
+ * assert.equal(between(3), true)
705
+ * assert.equal(between(-1), false)
706
+ * assert.equal(between(6), false)
228
707
  * ```
229
- *
230
- * @category predicates
231
- * @since 2.0.0
232
708
  */
233
709
  export const between = /*#__PURE__*/order.between(Order);
234
710
  /**
235
- * Restricts the given `number` to be within the range specified by the `minimum` and `maximum` values.
711
+ * Restricts the given `number` to be within the range specified by the
712
+ * `minimum` and `maximum` values.
236
713
  *
237
- * - If the `number` is less than the `minimum` value, the function returns the `minimum` value.
238
- * - If the `number` is greater than the `maximum` value, the function returns the `maximum` value.
714
+ * - If the `number` is less than the `minimum` value, the function returns the
715
+ * `minimum` value.
716
+ * - If the `number` is greater than the `maximum` value, the function returns the
717
+ * `maximum` value.
239
718
  * - Otherwise, it returns the original `number`.
240
719
  *
720
+ * @memberof Number
721
+ * @since 2.0.0
241
722
  * @example
723
+ *
242
724
  * ```ts
243
- * import * as assert from "node:assert"
725
+ * import * as assert from "node:assert/strict"
244
726
  * import { Number } from "effect"
245
727
  *
246
728
  * const clamp = Number.clamp({ minimum: 1, maximum: 5 })
@@ -249,152 +731,122 @@ export const between = /*#__PURE__*/order.between(Order);
249
731
  * assert.equal(clamp(0), 1)
250
732
  * assert.equal(clamp(6), 5)
251
733
  * ```
252
- *
253
- * @since 2.0.0
254
734
  */
255
735
  export const clamp = /*#__PURE__*/order.clamp(Order);
256
736
  /**
257
737
  * Returns the minimum between two `number`s.
258
738
  *
739
+ * @memberof Number
740
+ * @since 2.0.0
259
741
  * @example
742
+ *
260
743
  * ```ts
261
- * import * as assert from "node:assert"
744
+ * import * as assert from "node:assert/strict"
262
745
  * import { min } from "effect/Number"
263
746
  *
264
- * assert.deepStrictEqual(min(2, 3), 2)
747
+ * assert.equal(min(2, 3), 2)
265
748
  * ```
266
- *
267
- * @since 2.0.0
268
749
  */
269
750
  export const min = /*#__PURE__*/order.min(Order);
270
751
  /**
271
752
  * Returns the maximum between two `number`s.
272
753
  *
754
+ * @memberof Number
755
+ * @since 2.0.0
273
756
  * @example
757
+ *
274
758
  * ```ts
275
- * import * as assert from "node:assert"
759
+ * import * as assert from "node:assert/strict"
276
760
  * import { max } from "effect/Number"
277
761
  *
278
- * assert.deepStrictEqual(max(2, 3), 3)
762
+ * assert.equal(max(2, 3), 3)
279
763
  * ```
280
- *
281
- * @since 2.0.0
282
764
  */
283
765
  export const max = /*#__PURE__*/order.max(Order);
284
766
  /**
285
767
  * Determines the sign of a given `number`.
286
768
  *
769
+ * @memberof Number
770
+ * @since 2.0.0
771
+ * @category math
287
772
  * @example
773
+ *
288
774
  * ```ts
289
- * import * as assert from "node:assert"
775
+ * import * as assert from "node:assert/strict"
290
776
  * import { sign } from "effect/Number"
291
777
  *
292
- * assert.deepStrictEqual(sign(-5), -1)
293
- * assert.deepStrictEqual(sign(0), 0)
294
- * assert.deepStrictEqual(sign(5), 1)
778
+ * assert.equal(sign(-5), -1)
779
+ * assert.equal(sign(0), 0)
780
+ * assert.equal(sign(5), 1)
295
781
  * ```
296
- *
297
- * @category math
298
- * @since 2.0.0
299
782
  */
300
783
  export const sign = n => Order(n, 0);
301
784
  /**
302
- * Takes an `Iterable` of `number`s and returns their sum as a single `number`.
303
- *
304
- * @example
305
- * ```ts
306
- * import * as assert from "node:assert"
307
- * import { sumAll } from "effect/Number"
785
+ * Returns the remainder left over when one operand is divided by a second
786
+ * operand.
308
787
  *
309
- * assert.deepStrictEqual(sumAll([2, 3, 4]), 9)
310
- * ```
788
+ * It always takes the sign of the dividend.
311
789
  *
312
- * @category math
790
+ * @memberof Number
313
791
  * @since 2.0.0
314
- */
315
- export const sumAll = collection => {
316
- let out = 0;
317
- for (const n of collection) {
318
- out += n;
319
- }
320
- return out;
321
- };
322
- /**
323
- * Takes an `Iterable` of `number`s and returns their multiplication as a single `number`.
324
- *
325
- * @example
326
- * ```ts
327
- * import * as assert from "node:assert"
328
- * import { multiplyAll } from "effect/Number"
329
- *
330
- * assert.deepStrictEqual(multiplyAll([2, 3, 4]), 24)
331
- * ```
332
- *
333
792
  * @category math
334
- * @since 2.0.0
335
- */
336
- export const multiplyAll = collection => {
337
- let out = 1;
338
- for (const n of collection) {
339
- if (n === 0) {
340
- return 0;
341
- }
342
- out *= n;
343
- }
344
- return out;
345
- };
346
- /**
347
- * Returns the remainder left over when one operand is divided by a second operand.
348
- *
349
- * It always takes the sign of the dividend.
350
- *
351
793
  * @example
794
+ *
352
795
  * ```ts
353
- * import * as assert from "node:assert"
796
+ * import * as assert from "node:assert/strict"
354
797
  * import { remainder } from "effect/Number"
355
798
  *
356
- * assert.deepStrictEqual(remainder(2, 2), 0)
357
- * assert.deepStrictEqual(remainder(3, 2), 1)
358
- * assert.deepStrictEqual(remainder(-4, 2), -0)
799
+ * assert.equal(remainder(2, 2), 0)
800
+ * assert.equal(remainder(3, 2), 1)
801
+ * assert.equal(remainder(-4, 2), -0)
359
802
  * ```
360
- *
361
- * @category math
362
- * @since 2.0.0
363
803
  */
364
- export const remainder = /*#__PURE__*/dual(2, (self, divisor) => {
804
+ export const remainder = /*#__PURE__*/dual(2, (dividend, divisor) => {
365
805
  // https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034
366
- const selfDecCount = (self.toString().split(".")[1] || "").length;
806
+ const selfDecCount = (dividend.toString().split(".")[1] || "").length;
367
807
  const divisorDecCount = (divisor.toString().split(".")[1] || "").length;
368
808
  const decCount = selfDecCount > divisorDecCount ? selfDecCount : divisorDecCount;
369
- const selfInt = parseInt(self.toFixed(decCount).replace(".", ""));
809
+ const selfInt = parseInt(dividend.toFixed(decCount).replace(".", ""));
370
810
  const divisorInt = parseInt(divisor.toFixed(decCount).replace(".", ""));
371
811
  return selfInt % divisorInt / Math.pow(10, decCount);
372
812
  });
373
813
  /**
374
- * Returns the next power of 2 from the given number.
814
+ * Returns the next power of 2 greater than or equal to the given number.
815
+ *
816
+ * - For `positive` inputs, returns the smallest power of 2 that is >= the input
817
+ * - For `zero`, returns 2
818
+ * - For `negative` inputs, returns NaN (as logarithms of negative numbers are
819
+ * undefined)
820
+ * - For `NaN` input, returns NaN
821
+ * - For `Infinity`, returns Infinity
375
822
  *
823
+ * @memberof Number
824
+ * @since 2.0.0
825
+ * @category math
376
826
  * @example
827
+ *
377
828
  * ```ts
378
- * import * as assert from "node:assert"
829
+ * import * as assert from "node:assert/strict"
379
830
  * import { nextPow2 } from "effect/Number"
380
831
  *
381
- * assert.deepStrictEqual(nextPow2(5), 8)
382
- * assert.deepStrictEqual(nextPow2(17), 32)
832
+ * assert.equal(nextPow2(5), 8)
833
+ * assert.equal(nextPow2(17), 32)
834
+ * assert.equal(nextPow2(0), 2)
835
+ * assert.equal(Number.isNaN(nextPow2(-1)), true) // Negative inputs result in NaN
383
836
  * ```
384
- *
385
- * @category math
386
- * @since 2.0.0
387
837
  */
388
838
  export const nextPow2 = n => {
389
839
  const nextPow = Math.ceil(Math.log(n) / Math.log(2));
390
840
  return Math.max(Math.pow(2, nextPow), 2);
391
841
  };
392
842
  /**
393
- * Tries to parse a `number` from a `string` using the `Number()` function.
394
- * The following special string values are supported: "NaN", "Infinity", "-Infinity".
843
+ * Tries to parse a `number` from a `string` using the `Number()` function. The
844
+ * following special string values are supported: "NaN", "Infinity",
845
+ * "-Infinity".
395
846
  *
396
- * @category constructors
847
+ * @memberof Number
397
848
  * @since 2.0.0
849
+ * @category constructors
398
850
  */
399
851
  export const parse = s => {
400
852
  if (s === "NaN") {
@@ -415,17 +867,18 @@ export const parse = s => {
415
867
  /**
416
868
  * Returns the number rounded with the given precision.
417
869
  *
870
+ * @memberof Number
871
+ * @since 3.8.0
872
+ * @category math
418
873
  * @example
874
+ *
419
875
  * ```ts
420
- * import * as assert from "node:assert"
876
+ * import * as assert from "node:assert/strict"
421
877
  * import { round } from "effect/Number"
422
878
  *
423
- * assert.deepStrictEqual(round(1.1234, 2), 1.12)
424
- * assert.deepStrictEqual(round(1.567, 2), 1.57)
879
+ * assert.equal(round(1.1234, 2), 1.12)
880
+ * assert.equal(round(1.567, 2), 1.57)
425
881
  * ```
426
- *
427
- * @category math
428
- * @since 3.8.0
429
882
  */
430
883
  export const round = /*#__PURE__*/dual(2, (self, precision) => {
431
884
  const factor = Math.pow(10, precision);