not-so-float 1.2.1 → 2.1.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 +114 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -72
- package/dist/index.d.ts +8 -72
- package/dist/index.js +110 -70
- 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,20 @@ var Union = class {
|
|
|
227
173
|
contains(value) {
|
|
228
174
|
return this.intervals.some((i) => i.contains(value));
|
|
229
175
|
}
|
|
176
|
+
subset(other) {
|
|
177
|
+
return this.intervals.every(
|
|
178
|
+
(thisInterval) => other.intervals.some((otherInterval) => thisInterval.subset(otherInterval))
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
superset(other) {
|
|
182
|
+
return other.intervals.every(
|
|
183
|
+
(otherInterval) => this.intervals.some((thisInterval) => thisInterval.superset(otherInterval))
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
hull() {
|
|
187
|
+
if (this.isEmpty()) return EMPTY;
|
|
188
|
+
return single(this.lower(), this.upper());
|
|
189
|
+
}
|
|
230
190
|
forEach(callback) {
|
|
231
191
|
this.intervals.forEach(callback);
|
|
232
192
|
}
|
|
@@ -310,10 +270,17 @@ function makeBinaryOpEither(op) {
|
|
|
310
270
|
return op(toUnion(A), toUnion(B));
|
|
311
271
|
};
|
|
312
272
|
}
|
|
273
|
+
function single(a, b) {
|
|
274
|
+
if (typeof b === "undefined") {
|
|
275
|
+
b = a;
|
|
276
|
+
}
|
|
277
|
+
return union([interval(a, b)]);
|
|
278
|
+
}
|
|
313
279
|
function bounded(x) {
|
|
314
|
-
return
|
|
280
|
+
return single(prev(x), next(x));
|
|
315
281
|
}
|
|
316
282
|
var EMPTY = new Union([]);
|
|
283
|
+
var FULL = new Union([new Interval(-Infinity, Infinity)]);
|
|
317
284
|
|
|
318
285
|
// src/compare.ts
|
|
319
286
|
function ioverlap(a, b) {
|
|
@@ -471,6 +438,8 @@ function leftDiv(a, b) {
|
|
|
471
438
|
if (b === -Infinity) {
|
|
472
439
|
return Math.sign(-a) * 0;
|
|
473
440
|
}
|
|
441
|
+
if (b === 1) return a;
|
|
442
|
+
if (b === -1) return -a;
|
|
474
443
|
return prev(a / b);
|
|
475
444
|
}
|
|
476
445
|
function rightDiv(a, b) {
|
|
@@ -480,6 +449,8 @@ function rightDiv(a, b) {
|
|
|
480
449
|
if (b === -Infinity) {
|
|
481
450
|
return Math.sign(-a) * 0;
|
|
482
451
|
}
|
|
452
|
+
if (b === 1) return a;
|
|
453
|
+
if (b === -1) return -a;
|
|
483
454
|
return next(a / b);
|
|
484
455
|
}
|
|
485
456
|
function intervalType(x) {
|
|
@@ -499,7 +470,7 @@ function idiv(x, y) {
|
|
|
499
470
|
return EMPTY;
|
|
500
471
|
}
|
|
501
472
|
if (xType === 5 /* Z */) {
|
|
502
|
-
return
|
|
473
|
+
return single(0);
|
|
503
474
|
}
|
|
504
475
|
const [a, b] = [x.lo, x.hi];
|
|
505
476
|
const [c, d] = [y.lo, y.hi];
|
|
@@ -521,7 +492,7 @@ function idiv(x, y) {
|
|
|
521
492
|
} else if (xType === 1 /* P0 */) {
|
|
522
493
|
return union([new Interval(0, Infinity)]);
|
|
523
494
|
} else if (xType === 2 /* M */) {
|
|
524
|
-
return
|
|
495
|
+
return FULL;
|
|
525
496
|
} else if (xType === 3 /* N0 */) {
|
|
526
497
|
return union([new Interval(-Infinity, -0)]);
|
|
527
498
|
} else {
|
|
@@ -539,7 +510,7 @@ function idiv(x, y) {
|
|
|
539
510
|
new Interval(leftDiv(b, c), Infinity)
|
|
540
511
|
]);
|
|
541
512
|
} else {
|
|
542
|
-
return
|
|
513
|
+
return FULL;
|
|
543
514
|
}
|
|
544
515
|
} else if (yType === 3 /* N0 */) {
|
|
545
516
|
if (xType === 0 /* P1 */) {
|
|
@@ -547,7 +518,7 @@ function idiv(x, y) {
|
|
|
547
518
|
} else if (xType === 1 /* P0 */) {
|
|
548
519
|
return union([new Interval(-Infinity, -0)]);
|
|
549
520
|
} else if (xType === 2 /* M */) {
|
|
550
|
-
return
|
|
521
|
+
return FULL;
|
|
551
522
|
} else if (xType === 3 /* N0 */) {
|
|
552
523
|
return union([new Interval(0, Infinity)]);
|
|
553
524
|
} else {
|
|
@@ -575,6 +546,7 @@ function uneg(U) {
|
|
|
575
546
|
typeCheckIsUnion(U);
|
|
576
547
|
return new Union(U.intervals.slice().reverse().map(ineg));
|
|
577
548
|
}
|
|
549
|
+
var neg = makeUnaryOpEither(uneg);
|
|
578
550
|
var add = makeBinaryOpEither(uadd);
|
|
579
551
|
var sub = makeBinaryOpEither(usub);
|
|
580
552
|
var mul = makeBinaryOpEither(umul);
|
|
@@ -664,9 +636,7 @@ function ipowInt(X, n) {
|
|
|
664
636
|
} else if (X.hi < 0) {
|
|
665
637
|
return new Union([new Interval(leftPowInt(X.hi, n), rightPowInt(X.lo, n))]);
|
|
666
638
|
} else {
|
|
667
|
-
return new Union([
|
|
668
|
-
new Interval(0, rightPowInt(Math.max(Math.abs(X.hi), Math.abs(X.lo)), n))
|
|
669
|
-
]);
|
|
639
|
+
return new Union([new Interval(0, rightPowInt(Math.max(X.hi, -X.lo), n))]);
|
|
670
640
|
}
|
|
671
641
|
}
|
|
672
642
|
function upowInt(U, n) {
|
|
@@ -709,14 +679,84 @@ function usqinv(U) {
|
|
|
709
679
|
return union(uneg(x).intervals.concat(x.intervals));
|
|
710
680
|
}
|
|
711
681
|
var sqinv = makeUnaryOpEither(usqinv);
|
|
682
|
+
function upowIntInv(U, n) {
|
|
683
|
+
if (n === 0) {
|
|
684
|
+
if (U.contains(1)) return FULL;
|
|
685
|
+
else return EMPTY;
|
|
686
|
+
}
|
|
687
|
+
if (n === 1) {
|
|
688
|
+
return U;
|
|
689
|
+
}
|
|
690
|
+
if (n > 0 && n % 2 === 0) {
|
|
691
|
+
return upowEvenInv(U, n);
|
|
692
|
+
}
|
|
693
|
+
if (n > 0 && n % 2 !== 0) {
|
|
694
|
+
return upowOddInv(U, n);
|
|
695
|
+
}
|
|
696
|
+
if (U.lower() === 0 && U.upper() === 0) {
|
|
697
|
+
return EMPTY;
|
|
698
|
+
}
|
|
699
|
+
const one = new Union([new Interval(1, 1)]);
|
|
700
|
+
return div(one, upowIntInv(U, -n));
|
|
701
|
+
}
|
|
702
|
+
function powIntInv(A, n) {
|
|
703
|
+
typeCheckIsIntervalOrUnion(A);
|
|
704
|
+
return upowIntInv(toUnion(A), n);
|
|
705
|
+
}
|
|
706
|
+
function leftPowOddInv(y, n) {
|
|
707
|
+
if (y === 0) return 0;
|
|
708
|
+
if (y === 1) return 1;
|
|
709
|
+
if (y === -1) return -1;
|
|
710
|
+
else if (y > 0) return prev(Math.pow(y, prev(1 / n)));
|
|
711
|
+
else return prev(-Math.pow(-y, next(1 / n)));
|
|
712
|
+
}
|
|
713
|
+
function rightPowOddInv(y, n) {
|
|
714
|
+
if (y === 0) return 0;
|
|
715
|
+
if (y === 1) return 1;
|
|
716
|
+
if (y === -1) return -1;
|
|
717
|
+
else if (y > 0) return next(Math.pow(y, next(1 / n)));
|
|
718
|
+
else return next(-Math.pow(-y, prev(1 / n)));
|
|
719
|
+
}
|
|
720
|
+
function ipowOddInv(X, n) {
|
|
721
|
+
typeCheckIsInterval(X);
|
|
722
|
+
return new Interval(leftPowOddInv(X.lo, n), rightPowOddInv(X.hi, n));
|
|
723
|
+
}
|
|
724
|
+
function upowOddInv(U, n) {
|
|
725
|
+
typeCheckIsUnion(U);
|
|
726
|
+
return new Union(U.intervals.map((X) => ipowOddInv(X, n)));
|
|
727
|
+
}
|
|
728
|
+
function leftPowEvenInv(y, n) {
|
|
729
|
+
if (y === 0) return 0;
|
|
730
|
+
if (y === 1) return 1;
|
|
731
|
+
return prev(Math.pow(y, prev(1 / n)));
|
|
732
|
+
}
|
|
733
|
+
function rightPowEvenInv(y, n) {
|
|
734
|
+
if (y === 0) return 0;
|
|
735
|
+
if (y === 1) return 1;
|
|
736
|
+
return next(Math.pow(y, next(1 / n)));
|
|
737
|
+
}
|
|
738
|
+
function ipowEvenInv(Y, n) {
|
|
739
|
+
if (Y.hi < 0) {
|
|
740
|
+
return EMPTY;
|
|
741
|
+
} else if (Y.hi === 0) {
|
|
742
|
+
return new Union([new Interval(0, 0)]);
|
|
743
|
+
} else {
|
|
744
|
+
const principal = new Interval(
|
|
745
|
+
leftPowEvenInv(Math.max(0, Y.lo), n),
|
|
746
|
+
rightPowEvenInv(Y.hi, n)
|
|
747
|
+
);
|
|
748
|
+
return new Union([ineg(principal), principal]);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
function upowEvenInv(U, n) {
|
|
752
|
+
typeCheckIsUnion(U);
|
|
753
|
+
return union(U.intervals.map((X) => ipowEvenInv(X, n).intervals).flat());
|
|
754
|
+
}
|
|
712
755
|
|
|
713
756
|
// src/trigonometry.ts
|
|
714
757
|
var pi = Math.PI;
|
|
715
758
|
var halfpi = Math.PI / 2;
|
|
716
759
|
var tau = 2 * Math.PI;
|
|
717
|
-
function wrapAngle(angle) {
|
|
718
|
-
return (angle % tau + tau) % tau;
|
|
719
|
-
}
|
|
720
760
|
function piMultiples(X) {
|
|
721
761
|
const lower = Math.ceil(X.lo / Math.PI);
|
|
722
762
|
const upper = Math.floor(X.hi / Math.PI);
|
|
@@ -794,81 +834,28 @@ var tan = makeUnaryOpEither(utan);
|
|
|
794
834
|
bounded,
|
|
795
835
|
complement,
|
|
796
836
|
cos,
|
|
797
|
-
defaultNumbers,
|
|
798
837
|
disjoint,
|
|
799
838
|
div,
|
|
800
839
|
exp,
|
|
801
|
-
halfPiMultiples,
|
|
802
|
-
iabs,
|
|
803
|
-
iadd,
|
|
804
|
-
icos,
|
|
805
|
-
idisjoint,
|
|
806
|
-
idiv,
|
|
807
|
-
iexp,
|
|
808
|
-
iintersection,
|
|
809
|
-
ilog,
|
|
810
|
-
imax,
|
|
811
|
-
imin,
|
|
812
|
-
imul,
|
|
813
|
-
ineg,
|
|
814
|
-
inter,
|
|
815
840
|
intersection,
|
|
816
841
|
interval,
|
|
817
|
-
intervalType,
|
|
818
|
-
ioverlap,
|
|
819
|
-
ipow,
|
|
820
|
-
ipowInt,
|
|
821
|
-
isIntervalOrUnion,
|
|
822
|
-
isin,
|
|
823
|
-
isqrt,
|
|
824
|
-
isub,
|
|
825
|
-
iudisjoint,
|
|
826
|
-
iuoverlap,
|
|
827
|
-
leftMul,
|
|
828
842
|
log,
|
|
829
|
-
makeBinaryOpEither,
|
|
830
|
-
makeBinaryOpUnion,
|
|
831
|
-
makeUnaryOpEither,
|
|
832
|
-
makeUnaryOpUnion,
|
|
833
843
|
max,
|
|
834
844
|
min,
|
|
835
845
|
mul,
|
|
846
|
+
neg,
|
|
836
847
|
next,
|
|
837
848
|
overlap,
|
|
838
|
-
piMultiples,
|
|
839
849
|
pow,
|
|
840
850
|
powInt,
|
|
851
|
+
powIntInv,
|
|
841
852
|
prev,
|
|
842
|
-
rightMul,
|
|
843
853
|
sin,
|
|
854
|
+
single,
|
|
844
855
|
sqinv,
|
|
845
856
|
sqrt,
|
|
846
857
|
sub,
|
|
847
858
|
tan,
|
|
848
|
-
|
|
849
|
-
typeCheckIsInterval,
|
|
850
|
-
typeCheckIsIntervalOrUnion,
|
|
851
|
-
typeCheckIsUnion,
|
|
852
|
-
uabs,
|
|
853
|
-
uadd,
|
|
854
|
-
ucomplement,
|
|
855
|
-
ucos,
|
|
856
|
-
udiv,
|
|
857
|
-
uexp,
|
|
858
|
-
uintersection,
|
|
859
|
-
ulog,
|
|
860
|
-
umax,
|
|
861
|
-
umin,
|
|
862
|
-
umul,
|
|
863
|
-
uneg,
|
|
864
|
-
union,
|
|
865
|
-
upow,
|
|
866
|
-
upowInt,
|
|
867
|
-
usin,
|
|
868
|
-
usqinv,
|
|
869
|
-
usqrt,
|
|
870
|
-
usub,
|
|
871
|
-
utan,
|
|
872
|
-
wrapAngle
|
|
859
|
+
union
|
|
873
860
|
});
|
|
874
861
|
//# sourceMappingURL=index.cjs.map
|