@lvlte/ulp 1.1.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,7 +20,25 @@ export declare const ulp: typeof eps;
20
20
  * Exponent of a normalized floating-point number x.
21
21
  *
22
22
  * @param x The input number
23
- * @returns The largest integer `y` such that `2^y ≤ |x|`, or `NaN` if x is not
24
- * a finite number / if x is ±0.
23
+ * @returns The largest integer `y` such that `2^y ≤ |x|`. If `x` is not a
24
+ * finite number or equals ±0, returns `NaN`.
25
25
  */
26
26
  export declare function exponent(x: number): number;
27
+ /**
28
+ * Return the smallest representable floating-point number that comes after `x`
29
+ * on the float64 number line (towards +∞).
30
+ *
31
+ * @param x The input number
32
+ * @returns The smallest floating-point number `y` such that `y > x`. If `x` is
33
+ * `±Infinity` or `NaN`, returns `x`.
34
+ */
35
+ export declare function nextFloat(x: number): number;
36
+ /**
37
+ * Return the largest representable floating-point number that comes before `x`
38
+ * on the float64 number line (towards -∞).
39
+ *
40
+ * @param x The input number
41
+ * @returns The largest floating-point number `y` such that `y < x`. If `x` is
42
+ * `±Infinity` or `NaN`, returns `x`.
43
+ */
44
+ export declare function prevFloat(x: number): number;
package/dist/cjs/index.js CHANGED
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ulp = exports.FLOAT64_MIN = void 0;
4
4
  exports.eps = eps;
5
5
  exports.exponent = exponent;
6
+ exports.nextFloat = nextFloat;
7
+ exports.prevFloat = prevFloat;
6
8
  exports.FLOAT64_MIN = Math.pow(2, -1022);
7
9
  function eps(x = 1) {
8
10
  if (Number.isFinite(x)) {
@@ -25,3 +27,24 @@ function _exponent(x) {
25
27
  const s = x.toString(2);
26
28
  return x < 1 ? -(s.split('1', 1)[0].length - 1) : s.split('.', 1)[0].length - 1;
27
29
  }
30
+ function nextFloat(x) {
31
+ switch (x) {
32
+ case -Infinity:
33
+ return -Number.MAX_VALUE;
34
+ case Infinity:
35
+ case Number.MAX_VALUE:
36
+ return Infinity;
37
+ case -Number.MIN_VALUE:
38
+ return -0;
39
+ default:
40
+ if (!Number.isFinite(x)) {
41
+ return NaN;
42
+ }
43
+ }
44
+ const e = eps(x);
45
+ const y = x + e / 2;
46
+ return y > x ? y : x + e;
47
+ }
48
+ function prevFloat(x) {
49
+ return typeof x === 'number' ? -nextFloat(-x) : NaN;
50
+ }
package/dist/index.d.ts CHANGED
@@ -20,7 +20,25 @@ export declare const ulp: typeof eps;
20
20
  * Exponent of a normalized floating-point number x.
21
21
  *
22
22
  * @param x The input number
23
- * @returns The largest integer `y` such that `2^y ≤ |x|`, or `NaN` if x is not
24
- * a finite number / if x is ±0.
23
+ * @returns The largest integer `y` such that `2^y ≤ |x|`. If `x` is not a
24
+ * finite number or equals ±0, returns `NaN`.
25
25
  */
26
26
  export declare function exponent(x: number): number;
27
+ /**
28
+ * Return the smallest representable floating-point number that comes after `x`
29
+ * on the float64 number line (towards +∞).
30
+ *
31
+ * @param x The input number
32
+ * @returns The smallest floating-point number `y` such that `y > x`. If `x` is
33
+ * `±Infinity` or `NaN`, returns `x`.
34
+ */
35
+ export declare function nextFloat(x: number): number;
36
+ /**
37
+ * Return the largest representable floating-point number that comes before `x`
38
+ * on the float64 number line (towards -∞).
39
+ *
40
+ * @param x The input number
41
+ * @returns The largest floating-point number `y` such that `y < x`. If `x` is
42
+ * `±Infinity` or `NaN`, returns `x`.
43
+ */
44
+ export declare function prevFloat(x: number): number;
package/dist/index.js CHANGED
@@ -20,3 +20,24 @@ function _exponent(x) {
20
20
  const s = x.toString(2);
21
21
  return x < 1 ? -(s.split('1', 1)[0].length - 1) : s.split('.', 1)[0].length - 1;
22
22
  }
23
+ export function nextFloat(x) {
24
+ switch (x) {
25
+ case -Infinity:
26
+ return -Number.MAX_VALUE;
27
+ case Infinity:
28
+ case Number.MAX_VALUE:
29
+ return Infinity;
30
+ case -Number.MIN_VALUE:
31
+ return -0;
32
+ default:
33
+ if (!Number.isFinite(x)) {
34
+ return NaN;
35
+ }
36
+ }
37
+ const e = eps(x);
38
+ const y = x + e / 2;
39
+ return y > x ? y : x + e;
40
+ }
41
+ export function prevFloat(x) {
42
+ return typeof x === 'number' ? -nextFloat(-x) : NaN;
43
+ }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@lvlte/ulp",
3
- "version": "1.1.1",
4
- "description": "Compute the unit in last place of a given IEEE-754 64-bit number",
3
+ "version": "1.2.1",
4
+ "description": "Compute the ULP of a given number / Get the closest representable number that comes before/after it on the float64 number line",
5
5
  "license": "MIT",
6
6
  "author": "Eric Lavault <lvlte.code@gmail.com>",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/lvlte/ulp"
9
+ "url": "git+https://github.com/lvlte/ulp.git"
10
10
  },
11
11
  "type": "module",
12
12
  "main": "./dist/cjs/index.js",
@@ -38,17 +38,18 @@
38
38
  "keywords": [
39
39
  "number",
40
40
  "epsilon",
41
- "function",
42
41
  "precision",
43
42
  "eps",
44
43
  "ulp",
44
+ "nextFloat",
45
+ "prevFloat",
46
+ "next",
47
+ "previous",
45
48
  "float",
46
49
  "float64",
47
50
  "IEEE-754",
48
51
  "rounding",
49
52
  "tolerance",
50
- "compare",
51
- "equal",
52
53
  "ULP"
53
54
  ],
54
55
  "devDependencies": {
package/readme.md CHANGED
@@ -1,7 +1,10 @@
1
1
  # ulp (epsilon function)
2
2
 
3
- > Compute the [unit of least precision](https://en.wikipedia.org/wiki/Unit_in_the_last_place)
4
- of a given IEEE-754 64-bit number.
3
+ > Compute the [ULP](https://en.wikipedia.org/wiki/Unit_in_the_last_place)
4
+ of a given IEEE-754 64-bit number: `eps(x)` (alias: `ulp(x)`).<br>
5
+ > Get the closest representable number that comes before/after it on the float64
6
+ number line: `nextFloat(x)`, `prevFloat(x)`.
7
+
5
8
 
6
9
  ## Install
7
10
 
@@ -11,30 +14,51 @@ npm install @lvlte/ulp
11
14
 
12
15
  ## Usage
13
16
 
17
+ ### Import
18
+
14
19
  ```js
15
20
  // ESM
16
- import { eps } from '@lvlte/ulp';
21
+ import { eps, nextFloat, prevFloat } from '@lvlte/ulp';
17
22
  ```
18
23
  ```js
19
24
  // CJS
20
- const { eps } = require('@lvlte/ulp');
25
+ const { eps, nextFloat, prevFloat } = require('@lvlte/ulp');
21
26
  ```
27
+
28
+ ### eps(x) / ulp(x) (alias)
29
+ ```js
30
+ console.log( eps() ); // 2.220446049250313e-16
31
+ console.log( eps() === eps(1) ); // true
32
+ console.log( eps() === Number.EPSILON ); // true
33
+
34
+ console.log( eps(Number.MAX_SAFE_INTEGER) ); // 1
35
+ console.log( eps(Number.MAX_SAFE_INTEGER + 1) ); // 2
36
+
37
+ console.log( eps(0) ); // 5e-324
38
+ console.log( eps(0) === Number.MIN_VALUE ); // true
39
+
40
+ console.log( eps(Infinity) ); // NaN
41
+ ```
42
+
43
+ ### nextFloat(x) / prevFloat(x)
22
44
  ```js
23
- console.log(eps()); // 2.220446049250313e-16
24
- console.log(eps() === eps(1)); // true
25
- console.log(eps() === Number.EPSILON); // true
45
+ console.log( nextFloat(0) ); // 5e-324
46
+ console.log( nextFloat(0) === Number.MIN_VALUE ); // true
26
47
 
27
- console.log(eps(Number.MAX_SAFE_INTEGER)); // 1
28
- console.log(eps(Number.MAX_SAFE_INTEGER + 1)); // 2
48
+ console.log( nextFloat(1) ); // 1.0000000000000002
49
+ console.log( nextFloat(1) === 1 + eps(1) ); // true
29
50
 
30
- console.log(eps(0)); // 5e-324
31
- console.log(eps(0) === Number.MIN_VALUE); // true
51
+ console.log( nextFloat(Number.MAX_SAFE_INTEGER) ); // 9007199254740992
52
+ console.log( nextFloat(9007199254740992) ); // 9007199254740994
53
+ console.log( nextFloat(Number.MAX_VALUE) ); // Infinity
32
54
 
33
- console.log(eps(Infinity)); // NaN
55
+ console.log( prevFloat(0) ); // -5e-324
56
+ console.log( prevFloat(1) ); // 0.9999999999999999
57
+ console.log( prevFloat(9007199254740992) ); // 9007199254740991
58
+ console.log( prevFloat(Infinity) ); // 1.7976931348623157e+308
34
59
  ```
35
60
 
36
61
  ## Use case
37
62
 
38
- - Check whether two floating point numbers can be considered equal.
39
- - Approximate a floating point number x as a rational number.
40
- - Get the next/previous float on the float64 number line.
63
+ - Use the proper tolerance to check whether two floating-point numbers should be considered equal.
64
+ - Use the proper tolerance to approximate a floating-point number as a rational number.