not-so-float 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -8
- package/dist/index.cjs +105 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -72
- package/dist/index.d.ts +6 -72
- package/dist/index.js +101 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,9 +15,9 @@ Arithmetic** over IEEE 754 double precision floats (JS numbers).
|
|
|
15
15
|
```typescript
|
|
16
16
|
import * as nsf from "not-so-float";
|
|
17
17
|
|
|
18
|
-
const X = nsf.union([nsf.
|
|
19
|
-
const Y = nsf.union([nsf.
|
|
20
|
-
const Q = nsf.
|
|
18
|
+
const X = nsf.union([nsf.interval(-10, -1), nsf.interval(100, 120)]);
|
|
19
|
+
const Y = nsf.union([nsf.interval(-10, 2)]);
|
|
20
|
+
const Q = nsf.div(X, Y);
|
|
21
21
|
|
|
22
22
|
console.log(`(${X.toString()}) / ${Y.toString()} = ${Q.toString()}`);
|
|
23
23
|
```
|
|
@@ -112,16 +112,16 @@ interval represents:
|
|
|
112
112
|
Where $a$ and $b$ are real IEEE 754 values (not infinite).
|
|
113
113
|
The special case when both bounds are equal is called a _degenerate_ interval.
|
|
114
114
|
|
|
115
|
-
To construct an interval, use the `nsf.
|
|
115
|
+
To construct an interval, use the `nsf.interval()` function:
|
|
116
116
|
|
|
117
117
|
```typescript
|
|
118
|
-
nsf.
|
|
118
|
+
nsf.interval(a: number, b: number) : Interval
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
For example:
|
|
122
122
|
|
|
123
123
|
```typescript
|
|
124
|
-
> I = nsf.
|
|
124
|
+
> I = nsf.interval(0, 6)
|
|
125
125
|
Interval { lo: 0, hi: 6 }
|
|
126
126
|
```
|
|
127
127
|
|
|
@@ -133,6 +133,7 @@ class Interval {
|
|
|
133
133
|
isFinite(): boolean;
|
|
134
134
|
isDegenerate(): boolean;
|
|
135
135
|
contains(value: number): boolean;
|
|
136
|
+
hull(): Union;
|
|
136
137
|
superset(other: Interval): boolean;
|
|
137
138
|
subset(other: Interval): boolean;
|
|
138
139
|
toString(numbers?: (x: number) => string): string;
|
|
@@ -179,6 +180,17 @@ For example:
|
|
|
179
180
|
[ Interval { lo: 1, hi: 2 }, Interval { lo: 4, hi: 6 } ]
|
|
180
181
|
```
|
|
181
182
|
|
|
183
|
+
You can also use the shorthand `nsf.single()` to construct a singleton, i.e. a union with a single interval:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
const U = nsf.single(-0.1, 0.1);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Constants are also provided:
|
|
190
|
+
|
|
191
|
+
- `FULL`: all real numbers
|
|
192
|
+
- `EMPTY`: the empty union
|
|
193
|
+
|
|
182
194
|
## Set theory
|
|
183
195
|
|
|
184
196
|
Compare and compute intervals and unions with the following implementations of
|
|
@@ -244,5 +256,3 @@ function complement(A: Union | Interval): Union;
|
|
|
244
256
|
## Future improvements
|
|
245
257
|
|
|
246
258
|
- Support multiple rounding modes
|
|
247
|
-
- Add shortcut function for `nsf.union(nsf.inter([x]))`
|
|
248
|
-
- Change FULL constant to Union
|
package/dist/index.cjs
CHANGED
|
@@ -29,82 +29,29 @@ __export(index_exports, {
|
|
|
29
29
|
bounded: () => bounded,
|
|
30
30
|
complement: () => complement,
|
|
31
31
|
cos: () => cos,
|
|
32
|
-
defaultNumbers: () => defaultNumbers,
|
|
33
32
|
disjoint: () => disjoint,
|
|
34
33
|
div: () => div,
|
|
35
34
|
exp: () => exp,
|
|
36
|
-
halfPiMultiples: () => halfPiMultiples,
|
|
37
|
-
iabs: () => iabs,
|
|
38
|
-
iadd: () => iadd,
|
|
39
|
-
icos: () => icos,
|
|
40
|
-
idisjoint: () => idisjoint,
|
|
41
|
-
idiv: () => idiv,
|
|
42
|
-
iexp: () => iexp,
|
|
43
|
-
iintersection: () => iintersection,
|
|
44
|
-
ilog: () => ilog,
|
|
45
|
-
imax: () => imax,
|
|
46
|
-
imin: () => imin,
|
|
47
|
-
imul: () => imul,
|
|
48
|
-
ineg: () => ineg,
|
|
49
|
-
inter: () => inter,
|
|
50
35
|
intersection: () => intersection,
|
|
51
36
|
interval: () => interval,
|
|
52
|
-
intervalType: () => intervalType,
|
|
53
|
-
ioverlap: () => ioverlap,
|
|
54
|
-
ipow: () => ipow,
|
|
55
|
-
ipowInt: () => ipowInt,
|
|
56
|
-
isIntervalOrUnion: () => isIntervalOrUnion,
|
|
57
|
-
isin: () => isin,
|
|
58
|
-
isqrt: () => isqrt,
|
|
59
|
-
isub: () => isub,
|
|
60
|
-
iudisjoint: () => iudisjoint,
|
|
61
|
-
iuoverlap: () => iuoverlap,
|
|
62
|
-
leftMul: () => leftMul,
|
|
63
37
|
log: () => log,
|
|
64
|
-
makeBinaryOpEither: () => makeBinaryOpEither,
|
|
65
|
-
makeBinaryOpUnion: () => makeBinaryOpUnion,
|
|
66
|
-
makeUnaryOpEither: () => makeUnaryOpEither,
|
|
67
|
-
makeUnaryOpUnion: () => makeUnaryOpUnion,
|
|
68
38
|
max: () => max,
|
|
69
39
|
min: () => min,
|
|
70
40
|
mul: () => mul,
|
|
41
|
+
neg: () => neg,
|
|
71
42
|
next: () => next,
|
|
72
43
|
overlap: () => overlap,
|
|
73
|
-
piMultiples: () => piMultiples,
|
|
74
44
|
pow: () => pow,
|
|
75
45
|
powInt: () => powInt,
|
|
46
|
+
powIntInv: () => powIntInv,
|
|
76
47
|
prev: () => prev,
|
|
77
|
-
rightMul: () => rightMul,
|
|
78
48
|
sin: () => sin,
|
|
49
|
+
single: () => single,
|
|
79
50
|
sqinv: () => sqinv,
|
|
80
51
|
sqrt: () => sqrt,
|
|
81
52
|
sub: () => sub,
|
|
82
53
|
tan: () => tan,
|
|
83
|
-
|
|
84
|
-
typeCheckIsInterval: () => typeCheckIsInterval,
|
|
85
|
-
typeCheckIsIntervalOrUnion: () => typeCheckIsIntervalOrUnion,
|
|
86
|
-
typeCheckIsUnion: () => typeCheckIsUnion,
|
|
87
|
-
uabs: () => uabs,
|
|
88
|
-
uadd: () => uadd,
|
|
89
|
-
ucomplement: () => ucomplement,
|
|
90
|
-
ucos: () => ucos,
|
|
91
|
-
udiv: () => udiv,
|
|
92
|
-
uexp: () => uexp,
|
|
93
|
-
uintersection: () => uintersection,
|
|
94
|
-
ulog: () => ulog,
|
|
95
|
-
umax: () => umax,
|
|
96
|
-
umin: () => umin,
|
|
97
|
-
umul: () => umul,
|
|
98
|
-
uneg: () => uneg,
|
|
99
|
-
union: () => union,
|
|
100
|
-
upow: () => upow,
|
|
101
|
-
upowInt: () => upowInt,
|
|
102
|
-
usin: () => usin,
|
|
103
|
-
usqinv: () => usqinv,
|
|
104
|
-
usqrt: () => usqrt,
|
|
105
|
-
usub: () => usub,
|
|
106
|
-
utan: () => utan,
|
|
107
|
-
wrapAngle: () => wrapAngle
|
|
54
|
+
union: () => union
|
|
108
55
|
});
|
|
109
56
|
module.exports = __toCommonJS(index_exports);
|
|
110
57
|
|
|
@@ -196,14 +143,13 @@ function interval(a, b) {
|
|
|
196
143
|
}
|
|
197
144
|
return new Interval(a, b);
|
|
198
145
|
}
|
|
199
|
-
var inter = interval;
|
|
200
|
-
var FULL = new Interval(-Infinity, Infinity);
|
|
201
146
|
function typeCheckIsInterval(x) {
|
|
202
147
|
if (!(x instanceof Interval)) {
|
|
203
148
|
throw TypeError(`Argument must be an interval (got type ${typeof x})`);
|
|
204
149
|
}
|
|
205
150
|
return true;
|
|
206
151
|
}
|
|
152
|
+
var IFULL = new Interval(-Infinity, Infinity);
|
|
207
153
|
|
|
208
154
|
// src/union.ts
|
|
209
155
|
var Union = class {
|
|
@@ -227,6 +173,10 @@ var Union = class {
|
|
|
227
173
|
contains(value) {
|
|
228
174
|
return this.intervals.some((i) => i.contains(value));
|
|
229
175
|
}
|
|
176
|
+
hull() {
|
|
177
|
+
if (this.isEmpty()) return EMPTY;
|
|
178
|
+
return single(this.lower(), this.upper());
|
|
179
|
+
}
|
|
230
180
|
forEach(callback) {
|
|
231
181
|
this.intervals.forEach(callback);
|
|
232
182
|
}
|
|
@@ -310,10 +260,17 @@ function makeBinaryOpEither(op) {
|
|
|
310
260
|
return op(toUnion(A), toUnion(B));
|
|
311
261
|
};
|
|
312
262
|
}
|
|
263
|
+
function single(a, b) {
|
|
264
|
+
if (typeof b === "undefined") {
|
|
265
|
+
b = a;
|
|
266
|
+
}
|
|
267
|
+
return union([interval(a, b)]);
|
|
268
|
+
}
|
|
313
269
|
function bounded(x) {
|
|
314
|
-
return
|
|
270
|
+
return single(prev(x), next(x));
|
|
315
271
|
}
|
|
316
272
|
var EMPTY = new Union([]);
|
|
273
|
+
var FULL = new Union([new Interval(-Infinity, Infinity)]);
|
|
317
274
|
|
|
318
275
|
// src/compare.ts
|
|
319
276
|
function ioverlap(a, b) {
|
|
@@ -471,6 +428,8 @@ function leftDiv(a, b) {
|
|
|
471
428
|
if (b === -Infinity) {
|
|
472
429
|
return Math.sign(-a) * 0;
|
|
473
430
|
}
|
|
431
|
+
if (b === 1) return a;
|
|
432
|
+
if (b === -1) return -a;
|
|
474
433
|
return prev(a / b);
|
|
475
434
|
}
|
|
476
435
|
function rightDiv(a, b) {
|
|
@@ -480,6 +439,8 @@ function rightDiv(a, b) {
|
|
|
480
439
|
if (b === -Infinity) {
|
|
481
440
|
return Math.sign(-a) * 0;
|
|
482
441
|
}
|
|
442
|
+
if (b === 1) return a;
|
|
443
|
+
if (b === -1) return -a;
|
|
483
444
|
return next(a / b);
|
|
484
445
|
}
|
|
485
446
|
function intervalType(x) {
|
|
@@ -499,7 +460,7 @@ function idiv(x, y) {
|
|
|
499
460
|
return EMPTY;
|
|
500
461
|
}
|
|
501
462
|
if (xType === 5 /* Z */) {
|
|
502
|
-
return
|
|
463
|
+
return single(0);
|
|
503
464
|
}
|
|
504
465
|
const [a, b] = [x.lo, x.hi];
|
|
505
466
|
const [c, d] = [y.lo, y.hi];
|
|
@@ -521,7 +482,7 @@ function idiv(x, y) {
|
|
|
521
482
|
} else if (xType === 1 /* P0 */) {
|
|
522
483
|
return union([new Interval(0, Infinity)]);
|
|
523
484
|
} else if (xType === 2 /* M */) {
|
|
524
|
-
return
|
|
485
|
+
return FULL;
|
|
525
486
|
} else if (xType === 3 /* N0 */) {
|
|
526
487
|
return union([new Interval(-Infinity, -0)]);
|
|
527
488
|
} else {
|
|
@@ -539,7 +500,7 @@ function idiv(x, y) {
|
|
|
539
500
|
new Interval(leftDiv(b, c), Infinity)
|
|
540
501
|
]);
|
|
541
502
|
} else {
|
|
542
|
-
return
|
|
503
|
+
return FULL;
|
|
543
504
|
}
|
|
544
505
|
} else if (yType === 3 /* N0 */) {
|
|
545
506
|
if (xType === 0 /* P1 */) {
|
|
@@ -547,7 +508,7 @@ function idiv(x, y) {
|
|
|
547
508
|
} else if (xType === 1 /* P0 */) {
|
|
548
509
|
return union([new Interval(-Infinity, -0)]);
|
|
549
510
|
} else if (xType === 2 /* M */) {
|
|
550
|
-
return
|
|
511
|
+
return FULL;
|
|
551
512
|
} else if (xType === 3 /* N0 */) {
|
|
552
513
|
return union([new Interval(0, Infinity)]);
|
|
553
514
|
} else {
|
|
@@ -575,6 +536,7 @@ function uneg(U) {
|
|
|
575
536
|
typeCheckIsUnion(U);
|
|
576
537
|
return new Union(U.intervals.slice().reverse().map(ineg));
|
|
577
538
|
}
|
|
539
|
+
var neg = makeUnaryOpEither(uneg);
|
|
578
540
|
var add = makeBinaryOpEither(uadd);
|
|
579
541
|
var sub = makeBinaryOpEither(usub);
|
|
580
542
|
var mul = makeBinaryOpEither(umul);
|
|
@@ -658,13 +620,13 @@ function ipowInt(X, n) {
|
|
|
658
620
|
throw Error(`ipowint: exponent must be an integer, got ${n}`);
|
|
659
621
|
}
|
|
660
622
|
if (n < 0) return idiv(new Interval(1, 1), ipowInt(X, -n).intervals[0]);
|
|
661
|
-
if (n === 0) return new Union([
|
|
623
|
+
if (n === 0) return new Union([new Interval(1, 1)]);
|
|
662
624
|
if (X.lo > 0 || n % 2 !== 0) {
|
|
663
625
|
return new Union([new Interval(leftPowInt(X.lo, n), rightPowInt(X.hi, n))]);
|
|
664
626
|
} else if (X.hi < 0) {
|
|
665
627
|
return new Union([new Interval(leftPowInt(X.hi, n), rightPowInt(X.lo, n))]);
|
|
666
628
|
} else {
|
|
667
|
-
return new Union([new Interval(0, rightPowInt(Math.
|
|
629
|
+
return new Union([new Interval(0, rightPowInt(Math.max(X.hi, -X.lo), n))]);
|
|
668
630
|
}
|
|
669
631
|
}
|
|
670
632
|
function upowInt(U, n) {
|
|
@@ -707,14 +669,84 @@ function usqinv(U) {
|
|
|
707
669
|
return union(uneg(x).intervals.concat(x.intervals));
|
|
708
670
|
}
|
|
709
671
|
var sqinv = makeUnaryOpEither(usqinv);
|
|
672
|
+
function upowIntInv(U, n) {
|
|
673
|
+
if (n === 0) {
|
|
674
|
+
if (U.contains(1)) return FULL;
|
|
675
|
+
else return EMPTY;
|
|
676
|
+
}
|
|
677
|
+
if (n === 1) {
|
|
678
|
+
return U;
|
|
679
|
+
}
|
|
680
|
+
if (n > 0 && n % 2 === 0) {
|
|
681
|
+
return upowEvenInv(U, n);
|
|
682
|
+
}
|
|
683
|
+
if (n > 0 && n % 2 !== 0) {
|
|
684
|
+
return upowOddInv(U, n);
|
|
685
|
+
}
|
|
686
|
+
if (U.lower() === 0 && U.upper() === 0) {
|
|
687
|
+
return EMPTY;
|
|
688
|
+
}
|
|
689
|
+
const one = new Union([new Interval(1, 1)]);
|
|
690
|
+
return div(one, upowIntInv(U, -n));
|
|
691
|
+
}
|
|
692
|
+
function powIntInv(A, n) {
|
|
693
|
+
typeCheckIsIntervalOrUnion(A);
|
|
694
|
+
return upowIntInv(toUnion(A), n);
|
|
695
|
+
}
|
|
696
|
+
function leftPowOddInv(y, n) {
|
|
697
|
+
if (y === 0) return 0;
|
|
698
|
+
if (y === 1) return 1;
|
|
699
|
+
if (y === -1) return -1;
|
|
700
|
+
else if (y > 0) return prev(Math.pow(y, prev(1 / n)));
|
|
701
|
+
else return prev(-Math.pow(-y, next(1 / n)));
|
|
702
|
+
}
|
|
703
|
+
function rightPowOddInv(y, n) {
|
|
704
|
+
if (y === 0) return 0;
|
|
705
|
+
if (y === 1) return 1;
|
|
706
|
+
if (y === -1) return -1;
|
|
707
|
+
else if (y > 0) return next(Math.pow(y, next(1 / n)));
|
|
708
|
+
else return next(-Math.pow(-y, prev(1 / n)));
|
|
709
|
+
}
|
|
710
|
+
function ipowOddInv(X, n) {
|
|
711
|
+
typeCheckIsInterval(X);
|
|
712
|
+
return new Interval(leftPowOddInv(X.lo, n), rightPowOddInv(X.hi, n));
|
|
713
|
+
}
|
|
714
|
+
function upowOddInv(U, n) {
|
|
715
|
+
typeCheckIsUnion(U);
|
|
716
|
+
return new Union(U.intervals.map((X) => ipowOddInv(X, n)));
|
|
717
|
+
}
|
|
718
|
+
function leftPowEvenInv(y, n) {
|
|
719
|
+
if (y === 0) return 0;
|
|
720
|
+
if (y === 1) return 1;
|
|
721
|
+
return prev(Math.pow(y, prev(1 / n)));
|
|
722
|
+
}
|
|
723
|
+
function rightPowEvenInv(y, n) {
|
|
724
|
+
if (y === 0) return 0;
|
|
725
|
+
if (y === 1) return 1;
|
|
726
|
+
return next(Math.pow(y, next(1 / n)));
|
|
727
|
+
}
|
|
728
|
+
function ipowEvenInv(Y, n) {
|
|
729
|
+
if (Y.hi < 0) {
|
|
730
|
+
return EMPTY;
|
|
731
|
+
} else if (Y.hi === 0) {
|
|
732
|
+
return new Union([new Interval(0, 0)]);
|
|
733
|
+
} else {
|
|
734
|
+
const principal = new Interval(
|
|
735
|
+
leftPowEvenInv(Math.max(0, Y.lo), n),
|
|
736
|
+
rightPowEvenInv(Y.hi, n)
|
|
737
|
+
);
|
|
738
|
+
return new Union([ineg(principal), principal]);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
function upowEvenInv(U, n) {
|
|
742
|
+
typeCheckIsUnion(U);
|
|
743
|
+
return union(U.intervals.map((X) => ipowEvenInv(X, n).intervals).flat());
|
|
744
|
+
}
|
|
710
745
|
|
|
711
746
|
// src/trigonometry.ts
|
|
712
747
|
var pi = Math.PI;
|
|
713
748
|
var halfpi = Math.PI / 2;
|
|
714
749
|
var tau = 2 * Math.PI;
|
|
715
|
-
function wrapAngle(angle) {
|
|
716
|
-
return (angle % tau + tau) % tau;
|
|
717
|
-
}
|
|
718
750
|
function piMultiples(X) {
|
|
719
751
|
const lower = Math.ceil(X.lo / Math.PI);
|
|
720
752
|
const upper = Math.floor(X.hi / Math.PI);
|
|
@@ -792,81 +824,28 @@ var tan = makeUnaryOpEither(utan);
|
|
|
792
824
|
bounded,
|
|
793
825
|
complement,
|
|
794
826
|
cos,
|
|
795
|
-
defaultNumbers,
|
|
796
827
|
disjoint,
|
|
797
828
|
div,
|
|
798
829
|
exp,
|
|
799
|
-
halfPiMultiples,
|
|
800
|
-
iabs,
|
|
801
|
-
iadd,
|
|
802
|
-
icos,
|
|
803
|
-
idisjoint,
|
|
804
|
-
idiv,
|
|
805
|
-
iexp,
|
|
806
|
-
iintersection,
|
|
807
|
-
ilog,
|
|
808
|
-
imax,
|
|
809
|
-
imin,
|
|
810
|
-
imul,
|
|
811
|
-
ineg,
|
|
812
|
-
inter,
|
|
813
830
|
intersection,
|
|
814
831
|
interval,
|
|
815
|
-
intervalType,
|
|
816
|
-
ioverlap,
|
|
817
|
-
ipow,
|
|
818
|
-
ipowInt,
|
|
819
|
-
isIntervalOrUnion,
|
|
820
|
-
isin,
|
|
821
|
-
isqrt,
|
|
822
|
-
isub,
|
|
823
|
-
iudisjoint,
|
|
824
|
-
iuoverlap,
|
|
825
|
-
leftMul,
|
|
826
832
|
log,
|
|
827
|
-
makeBinaryOpEither,
|
|
828
|
-
makeBinaryOpUnion,
|
|
829
|
-
makeUnaryOpEither,
|
|
830
|
-
makeUnaryOpUnion,
|
|
831
833
|
max,
|
|
832
834
|
min,
|
|
833
835
|
mul,
|
|
836
|
+
neg,
|
|
834
837
|
next,
|
|
835
838
|
overlap,
|
|
836
|
-
piMultiples,
|
|
837
839
|
pow,
|
|
838
840
|
powInt,
|
|
841
|
+
powIntInv,
|
|
839
842
|
prev,
|
|
840
|
-
rightMul,
|
|
841
843
|
sin,
|
|
844
|
+
single,
|
|
842
845
|
sqinv,
|
|
843
846
|
sqrt,
|
|
844
847
|
sub,
|
|
845
848
|
tan,
|
|
846
|
-
|
|
847
|
-
typeCheckIsInterval,
|
|
848
|
-
typeCheckIsIntervalOrUnion,
|
|
849
|
-
typeCheckIsUnion,
|
|
850
|
-
uabs,
|
|
851
|
-
uadd,
|
|
852
|
-
ucomplement,
|
|
853
|
-
ucos,
|
|
854
|
-
udiv,
|
|
855
|
-
uexp,
|
|
856
|
-
uintersection,
|
|
857
|
-
ulog,
|
|
858
|
-
umax,
|
|
859
|
-
umin,
|
|
860
|
-
umul,
|
|
861
|
-
uneg,
|
|
862
|
-
union,
|
|
863
|
-
upow,
|
|
864
|
-
upowInt,
|
|
865
|
-
usin,
|
|
866
|
-
usqinv,
|
|
867
|
-
usqrt,
|
|
868
|
-
usub,
|
|
869
|
-
utan,
|
|
870
|
-
wrapAngle
|
|
849
|
+
union
|
|
871
850
|
});
|
|
872
851
|
//# sourceMappingURL=index.cjs.map
|