PrefixIntervalTree.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /**
  2. * Copyright (c) 2013-present, Facebook, Inc.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. *
  8. * @typechecks
  9. */
  10. 'use strict';
  11. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  12. var invariant = require("./invariant");
  13. var parent = function parent(node) {
  14. return Math.floor(node / 2);
  15. };
  16. var Int32Array = global.Int32Array || function (size) {
  17. var xs = [];
  18. for (var i = size - 1; i >= 0; --i) {
  19. xs[i] = 0;
  20. }
  21. return xs;
  22. };
  23. /**
  24. * Computes the next power of 2 after or equal to x.
  25. */
  26. function ceilLog2(x) {
  27. var y = 1;
  28. while (y < x) {
  29. y *= 2;
  30. }
  31. return y;
  32. }
  33. /**
  34. * A prefix interval tree stores an numeric array and the partial sums of that
  35. * array. It is optimized for updating the values of the array without
  36. * recomputing all of the partial sums.
  37. *
  38. * - O(ln n) update
  39. * - O(1) lookup
  40. * - O(ln n) compute a partial sum
  41. * - O(n) space
  42. *
  43. * Note that the sequence of partial sums is one longer than the array, so that
  44. * the first partial sum is always 0, and the last partial sum is the sum of the
  45. * entire array.
  46. */
  47. var PrefixIntervalTree =
  48. /*#__PURE__*/
  49. function () {
  50. /**
  51. * Number of elements in the array
  52. */
  53. /**
  54. * Half the size of the heap. It is also the number of non-leaf nodes, and the
  55. * index of the first element in the heap. Always a power of 2.
  56. */
  57. /**
  58. * Binary heap
  59. */
  60. function PrefixIntervalTree(xs) {
  61. _defineProperty(this, "_size", void 0);
  62. _defineProperty(this, "_half", void 0);
  63. _defineProperty(this, "_heap", void 0);
  64. this._size = xs.length;
  65. this._half = ceilLog2(this._size);
  66. this._heap = new Int32Array(2 * this._half);
  67. var i;
  68. for (i = 0; i < this._size; ++i) {
  69. this._heap[this._half + i] = xs[i];
  70. }
  71. for (i = this._half - 1; i > 0; --i) {
  72. this._heap[i] = this._heap[2 * i] + this._heap[2 * i + 1];
  73. }
  74. }
  75. PrefixIntervalTree.uniform = function uniform(size, initialValue) {
  76. var xs = [];
  77. for (var _i = size - 1; _i >= 0; --_i) {
  78. xs[_i] = initialValue;
  79. }
  80. return new PrefixIntervalTree(xs);
  81. };
  82. PrefixIntervalTree.empty = function empty(size) {
  83. return PrefixIntervalTree.uniform(size, 0);
  84. };
  85. var _proto = PrefixIntervalTree.prototype;
  86. _proto.set = function set(index, value) {
  87. !(0 <= index && index < this._size) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Index out of range %s', index) : invariant(false) : void 0;
  88. var node = this._half + index;
  89. this._heap[node] = value;
  90. node = parent(node);
  91. for (; node !== 0; node = parent(node)) {
  92. this._heap[node] = this._heap[2 * node] + this._heap[2 * node + 1];
  93. }
  94. };
  95. _proto.get = function get(index) {
  96. !(0 <= index && index < this._size) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Index out of range %s', index) : invariant(false) : void 0;
  97. var node = this._half + index;
  98. return this._heap[node];
  99. };
  100. _proto.getSize = function getSize() {
  101. return this._size;
  102. };
  103. /**
  104. * Returns the sum get(0) + get(1) + ... + get(end - 1).
  105. */
  106. _proto.sumUntil = function sumUntil(end) {
  107. !(0 <= end && end < this._size + 1) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Index out of range %s', end) : invariant(false) : void 0;
  108. if (end === 0) {
  109. return 0;
  110. }
  111. var node = this._half + end - 1;
  112. var sum = this._heap[node];
  113. for (; node !== 1; node = parent(node)) {
  114. if (node % 2 === 1) {
  115. sum += this._heap[node - 1];
  116. }
  117. }
  118. return sum;
  119. };
  120. /**
  121. * Returns the sum get(0) + get(1) + ... + get(inclusiveEnd).
  122. */
  123. _proto.sumTo = function sumTo(inclusiveEnd) {
  124. !(0 <= inclusiveEnd && inclusiveEnd < this._size) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Index out of range %s', inclusiveEnd) : invariant(false) : void 0;
  125. return this.sumUntil(inclusiveEnd + 1);
  126. };
  127. /**
  128. * Returns the sum get(begin) + get(begin + 1) + ... + get(end - 1).
  129. */
  130. _proto.sum = function sum(begin, end) {
  131. !(begin <= end) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Begin must precede end') : invariant(false) : void 0;
  132. return this.sumUntil(end) - this.sumUntil(begin);
  133. };
  134. /**
  135. * Returns the smallest i such that 0 <= i <= size and sumUntil(i) <= t, or
  136. * -1 if no such i exists.
  137. */
  138. _proto.greatestLowerBound = function greatestLowerBound(t) {
  139. if (t < 0) {
  140. return -1;
  141. }
  142. var node = 1;
  143. if (this._heap[node] <= t) {
  144. return this._size;
  145. }
  146. while (node < this._half) {
  147. var leftSum = this._heap[2 * node];
  148. if (t < leftSum) {
  149. node = 2 * node;
  150. } else {
  151. node = 2 * node + 1;
  152. t -= leftSum;
  153. }
  154. }
  155. return node - this._half;
  156. };
  157. /**
  158. * Returns the smallest i such that 0 <= i <= size and sumUntil(i) < t, or
  159. * -1 if no such i exists.
  160. */
  161. _proto.greatestStrictLowerBound = function greatestStrictLowerBound(t) {
  162. if (t <= 0) {
  163. return -1;
  164. }
  165. var node = 1;
  166. if (this._heap[node] < t) {
  167. return this._size;
  168. }
  169. while (node < this._half) {
  170. var leftSum = this._heap[2 * node];
  171. if (t <= leftSum) {
  172. node = 2 * node;
  173. } else {
  174. node = 2 * node + 1;
  175. t -= leftSum;
  176. }
  177. }
  178. return node - this._half;
  179. };
  180. /**
  181. * Returns the smallest i such that 0 <= i <= size and t <= sumUntil(i), or
  182. * size + 1 if no such i exists.
  183. */
  184. _proto.leastUpperBound = function leastUpperBound(t) {
  185. return this.greatestStrictLowerBound(t) + 1;
  186. };
  187. /**
  188. * Returns the smallest i such that 0 <= i <= size and t < sumUntil(i), or
  189. * size + 1 if no such i exists.
  190. */
  191. _proto.leastStrictUpperBound = function leastStrictUpperBound(t) {
  192. return this.greatestLowerBound(t) + 1;
  193. };
  194. return PrefixIntervalTree;
  195. }();
  196. module.exports = PrefixIntervalTree;