interval.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /**
  2. * Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { IntTuple as Tuple } from '../tuple';
  7. export const Empty = Tuple.Zero;
  8. export function ofRange(min: number, max: number) { return max < min ? Tuple.create(min, min) : Tuple.create(min, max + 1); }
  9. export function ofBounds(start: number, end: number) { return end <= start ? Tuple.create(start, start) : Tuple.create(start, end); }
  10. export function ofLength(length: number) { return length < 0 ? Tuple.create(0, 0) : Tuple.create(0, length); }
  11. export const is = Tuple.is;
  12. export const start = Tuple.fst;
  13. export const end = Tuple.snd;
  14. export const min = Tuple.fst;
  15. export function max(i: Tuple) { return Tuple.snd(i) - 1; }
  16. export function size(i: Tuple) { return Tuple.snd(i) - Tuple.fst(i); }
  17. export const hashCode = Tuple.hashCode;
  18. export const toString = Tuple.toString;
  19. export function has(int: Tuple, v: number) { return Tuple.fst(int) <= v && v < Tuple.snd(int); }
  20. /** Returns the index of `x` in `set` or -1 if not found. */
  21. export function indexOf(int: Tuple, x: number) { const m = start(int); return x >= m && x < end(int) ? x - m : -1; }
  22. export function getAt(int: Tuple, i: number) { return Tuple.fst(int) + i; }
  23. export const areEqual = Tuple.areEqual;
  24. export function areIntersecting(a: Tuple, b: Tuple) {
  25. const sa = size(a), sb = size(b);
  26. if (sa === 0 && sb === 0) return true;
  27. return sa > 0 && sb > 0 && max(a) >= min(b) && min(a) <= max(b);
  28. }
  29. export function isSubInterval(a: Tuple, b: Tuple) {
  30. if (!size(a)) return size(b) === 0;
  31. if (!size(b)) return true;
  32. return start(a) <= start(b) && end(a) >= end(b);
  33. }
  34. export function findPredecessorIndex(int: Tuple, v: number) {
  35. const s = start(int);
  36. if (v <= s) return 0;
  37. const e = end(int);
  38. if (v >= e) return e - s;
  39. return v - s;
  40. }
  41. export function findPredecessorIndexInInterval(int: Tuple, v: number, bounds: Tuple) {
  42. const bS = start(bounds);
  43. const s = start(int);
  44. if (v <= bS + s) return bS;
  45. const bE = end(bounds);
  46. if (v >= bE + s) return bE;
  47. return v - s;
  48. }
  49. export function findRange(int: Tuple, min: number, max: number) {
  50. return ofBounds(findPredecessorIndex(int, min), findPredecessorIndex(int, max + 1));
  51. }
  52. export function intersect(a: Tuple, b: Tuple) {
  53. if (!areIntersecting(a, b)) return Empty;
  54. return ofBounds(Math.max(start(a), start(b)), Math.min(end(a), end(b)));
  55. }
  56. export function intersectionSize(a: Tuple, b: Tuple) {
  57. return size(findRange(a, min(b), max(b)));
  58. }