not-so-float 1.2.1 → 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 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.inter(-10, -1), nsf.inter(100, 120)]);
19
- const Y = nsf.union([nsf.inter(-10, 2)]);
20
- const Q = nsf.udiv(X, Y);
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.inter()` function:
115
+ To construct an interval, use the `nsf.interval()` function:
116
116
 
117
117
  ```typescript
118
- nsf.inter(a: number, b: number) : Interval
118
+ nsf.interval(a: number, b: number) : Interval
119
119
  ```
120
120
 
121
121
  For example:
122
122
 
123
123
  ```typescript
124
- > I = nsf.inter(0, 6)
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
- toUnion: () => toUnion,
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 new Union([new Interval(prev(x), next(x))]);
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 union([inter(0, 0)]);
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 union([FULL]);
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 union([FULL]);
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 union([FULL]);
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);
@@ -664,9 +626,7 @@ function ipowInt(X, 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([
668
- new Interval(0, rightPowInt(Math.max(Math.abs(X.hi), Math.abs(X.lo)), n))
669
- ]);
629
+ return new Union([new Interval(0, rightPowInt(Math.max(X.hi, -X.lo), n))]);
670
630
  }
671
631
  }
672
632
  function upowInt(U, n) {
@@ -709,14 +669,84 @@ function usqinv(U) {
709
669
  return union(uneg(x).intervals.concat(x.intervals));
710
670
  }
711
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
+ }
712
745
 
713
746
  // src/trigonometry.ts
714
747
  var pi = Math.PI;
715
748
  var halfpi = Math.PI / 2;
716
749
  var tau = 2 * Math.PI;
717
- function wrapAngle(angle) {
718
- return (angle % tau + tau) % tau;
719
- }
720
750
  function piMultiples(X) {
721
751
  const lower = Math.ceil(X.lo / Math.PI);
722
752
  const upper = Math.floor(X.hi / Math.PI);
@@ -794,81 +824,28 @@ var tan = makeUnaryOpEither(utan);
794
824
  bounded,
795
825
  complement,
796
826
  cos,
797
- defaultNumbers,
798
827
  disjoint,
799
828
  div,
800
829
  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
830
  intersection,
816
831
  interval,
817
- intervalType,
818
- ioverlap,
819
- ipow,
820
- ipowInt,
821
- isIntervalOrUnion,
822
- isin,
823
- isqrt,
824
- isub,
825
- iudisjoint,
826
- iuoverlap,
827
- leftMul,
828
832
  log,
829
- makeBinaryOpEither,
830
- makeBinaryOpUnion,
831
- makeUnaryOpEither,
832
- makeUnaryOpUnion,
833
833
  max,
834
834
  min,
835
835
  mul,
836
+ neg,
836
837
  next,
837
838
  overlap,
838
- piMultiples,
839
839
  pow,
840
840
  powInt,
841
+ powIntInv,
841
842
  prev,
842
- rightMul,
843
843
  sin,
844
+ single,
844
845
  sqinv,
845
846
  sqrt,
846
847
  sub,
847
848
  tan,
848
- toUnion,
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
849
+ union
873
850
  });
874
851
  //# sourceMappingURL=index.cjs.map