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.
- package/dist/cjs/BigDecimal.js +3 -0
- package/dist/cjs/BigDecimal.js.map +1 -1
- package/dist/cjs/BigInt.js +3 -0
- package/dist/cjs/BigInt.js.map +1 -1
- package/dist/cjs/JSONSchema.js +24 -10
- package/dist/cjs/JSONSchema.js.map +1 -1
- package/dist/cjs/Number.js +650 -196
- package/dist/cjs/Number.js.map +1 -1
- package/dist/cjs/ParseResult.js +3 -1
- package/dist/cjs/ParseResult.js.map +1 -1
- package/dist/cjs/Schema.js +4 -2
- package/dist/cjs/Schema.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/dts/BigDecimal.d.ts +3 -0
- package/dist/dts/BigDecimal.d.ts.map +1 -1
- package/dist/dts/BigInt.d.ts +3 -0
- package/dist/dts/BigInt.d.ts.map +1 -1
- package/dist/dts/JSONSchema.d.ts.map +1 -1
- package/dist/dts/Number.d.ts +866 -421
- package/dist/dts/Number.d.ts.map +1 -1
- package/dist/dts/ParseResult.d.ts.map +1 -1
- package/dist/dts/Schema.d.ts +1 -3
- package/dist/dts/Schema.d.ts.map +1 -1
- package/dist/dts/index.d.ts +98 -3
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/BigDecimal.js +3 -0
- package/dist/esm/BigDecimal.js.map +1 -1
- package/dist/esm/BigInt.js +3 -0
- package/dist/esm/BigInt.js.map +1 -1
- package/dist/esm/JSONSchema.js +24 -10
- package/dist/esm/JSONSchema.js.map +1 -1
- package/dist/esm/Number.js +645 -192
- package/dist/esm/Number.js.map +1 -1
- package/dist/esm/ParseResult.js +2 -1
- package/dist/esm/ParseResult.js.map +1 -1
- package/dist/esm/Schema.js +4 -2
- package/dist/esm/Schema.js.map +1 -1
- package/dist/esm/index.js +98 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/package.json +1 -1
- package/src/BigDecimal.ts +3 -0
- package/src/BigInt.ts +3 -0
- package/src/JSONSchema.ts +20 -7
- package/src/Number.ts +913 -475
- package/src/ParseResult.ts +2 -1
- package/src/Schema.ts +11 -8
- package/src/index.ts +98 -3
- package/src/internal/version.ts +1 -1
package/dist/esm/Number.js
CHANGED
|
@@ -1,246 +1,728 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
22
|
-
* assert
|
|
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
|
-
* @
|
|
26
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
56
|
-
*
|
|
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
|
|
285
|
+
export const sumAll = collection => _Iterable.reduce(collection, 0, sum);
|
|
59
286
|
/**
|
|
60
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
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
|
|
397
|
+
export const multiply = /*#__PURE__*/dual(2, (multiplier, multiplicand) => multiplier * multiplicand);
|
|
74
398
|
/**
|
|
75
|
-
*
|
|
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
|
|
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
|
-
*
|
|
83
|
-
* assert.
|
|
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
|
-
* @
|
|
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, (
|
|
510
|
+
export const divide = /*#__PURE__*/dual(2, (dividend, divisor) => divisor === 0 ? option.none : option.some(dividend / divisor));
|
|
90
511
|
/**
|
|
91
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
104
|
-
* @
|
|
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, (
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
601
|
+
export const decrement = n => subtract(n, 1);
|
|
137
602
|
/**
|
|
138
|
-
* @
|
|
603
|
+
* @memberof Number
|
|
139
604
|
* @since 2.0.0
|
|
605
|
+
* @category instances
|
|
140
606
|
*/
|
|
141
607
|
export const Equivalence = equivalence.number;
|
|
142
608
|
/**
|
|
143
|
-
* @
|
|
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
|
|
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.
|
|
156
|
-
* assert.
|
|
157
|
-
* assert.
|
|
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
|
|
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.
|
|
173
|
-
* assert.
|
|
174
|
-
* assert.
|
|
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
|
|
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.
|
|
190
|
-
* assert.
|
|
191
|
-
* assert.
|
|
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
|
|
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.
|
|
207
|
-
* assert.
|
|
208
|
-
* assert.
|
|
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.
|
|
226
|
-
* assert.
|
|
227
|
-
* assert.
|
|
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
|
|
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
|
|
238
|
-
*
|
|
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.
|
|
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.
|
|
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.
|
|
293
|
-
* assert.
|
|
294
|
-
* assert.
|
|
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
|
-
*
|
|
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
|
-
*
|
|
310
|
-
* ```
|
|
788
|
+
* It always takes the sign of the dividend.
|
|
311
789
|
*
|
|
312
|
-
* @
|
|
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.
|
|
357
|
-
* assert.
|
|
358
|
-
* assert.
|
|
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, (
|
|
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 = (
|
|
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(
|
|
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
|
|
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.
|
|
382
|
-
* assert.
|
|
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
|
-
*
|
|
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
|
-
* @
|
|
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.
|
|
424
|
-
* assert.
|
|
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);
|