@rocicorp/zero 1.11.0-canary.23 → 1.11.0-canary.25

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.
Files changed (108) hide show
  1. package/out/shared/src/centroid.d.ts +0 -1
  2. package/out/shared/src/centroid.d.ts.map +1 -1
  3. package/out/shared/src/centroid.js +1 -4
  4. package/out/shared/src/centroid.js.map +1 -1
  5. package/out/shared/src/tdigest.d.ts +10 -0
  6. package/out/shared/src/tdigest.d.ts.map +1 -1
  7. package/out/shared/src/tdigest.js +147 -63
  8. package/out/shared/src/tdigest.js.map +1 -1
  9. package/out/z2s/src/compiler.d.ts.map +1 -1
  10. package/out/z2s/src/compiler.js +9 -5
  11. package/out/z2s/src/compiler.js.map +1 -1
  12. package/out/z2s/src/sql.d.ts.map +1 -1
  13. package/out/z2s/src/sql.js +7 -3
  14. package/out/z2s/src/sql.js.map +1 -1
  15. package/out/zero/package.js +1 -1
  16. package/out/zero/package.js.map +1 -1
  17. package/out/zero-cache/src/config/zero-config.d.ts +5 -0
  18. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  19. package/out/zero-cache/src/config/zero-config.js +14 -0
  20. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  21. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  22. package/out/zero-cache/src/db/migration-lite.js +5 -3
  23. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  24. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  25. package/out/zero-cache/src/server/change-streamer.js +5 -1
  26. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  27. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +38 -1
  28. package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -1
  29. package/out/zero-cache/src/services/change-source/common/replica-restore.js +27 -10
  30. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -1
  31. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts.map +1 -1
  32. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +29 -13
  33. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -1
  34. package/out/zero-cache/src/services/litestream/commands.d.ts +22 -1
  35. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  36. package/out/zero-cache/src/services/litestream/commands.js +80 -26
  37. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  38. package/out/zero-cache/src/services/litestream/config-v5.yml +1 -0
  39. package/out/zero-cache/src/services/litestream/wal-keeper.d.ts +33 -0
  40. package/out/zero-cache/src/services/litestream/wal-keeper.d.ts.map +1 -0
  41. package/out/zero-cache/src/services/litestream/wal-keeper.js +49 -0
  42. package/out/zero-cache/src/services/litestream/wal-keeper.js.map +1 -0
  43. package/out/zero-cache/src/services/replicator/change-processor.js +2 -0
  44. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  45. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  46. package/out/zero-cache/src/services/run-ast.js +14 -7
  47. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  48. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +8 -1
  49. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  50. package/out/zero-cache/src/services/view-syncer/cvr-store.js +51 -9
  51. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  52. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +25 -9
  53. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  54. package/out/zero-cache/src/services/view-syncer/cvr.js +76 -38
  55. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  56. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +20 -2
  57. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  58. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +103 -41
  59. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  60. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +1 -106
  61. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -1
  62. package/out/zero-cache/src/services/view-syncer/schema/types.js +5 -20
  63. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  64. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +10 -1
  65. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  66. package/out/zero-cache/src/services/view-syncer/snapshotter.js +45 -8
  67. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  68. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  69. package/out/zero-cache/src/services/view-syncer/view-syncer.js +17 -16
  70. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  71. package/out/zero-cache/src/types/pg-data-type.d.ts +2 -0
  72. package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
  73. package/out/zero-cache/src/types/pg-data-type.js +6 -1
  74. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  75. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  76. package/out/zero-cache/src/workers/replicator.js +15 -7
  77. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  78. package/out/zero-client/src/client/context.d.ts +1 -1
  79. package/out/zero-client/src/client/context.d.ts.map +1 -1
  80. package/out/zero-client/src/client/context.js +2 -1
  81. package/out/zero-client/src/client/context.js.map +1 -1
  82. package/out/zero-client/src/client/inspector/lazy-inspector.js +1 -1
  83. package/out/zero-client/src/client/query-manager.d.ts +9 -0
  84. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  85. package/out/zero-client/src/client/query-manager.js +3 -3
  86. package/out/zero-client/src/client/query-manager.js.map +1 -1
  87. package/out/zero-client/src/client/version.js +1 -1
  88. package/out/zero-client/src/client/zero.js +1 -1
  89. package/out/zero-server/src/schema.d.ts.map +1 -1
  90. package/out/zero-server/src/schema.js +1 -0
  91. package/out/zero-server/src/schema.js.map +1 -1
  92. package/out/zql/src/ivm/memory-source.d.ts +1 -1
  93. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  94. package/out/zql/src/ivm/memory-source.js +1 -1
  95. package/out/zql/src/ivm/memory-source.js.map +1 -1
  96. package/out/zql/src/query/measure-push-operator.d.ts +7 -1
  97. package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
  98. package/out/zql/src/query/measure-push-operator.js +22 -4
  99. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  100. package/out/zqlite/src/table-source.d.ts +5 -0
  101. package/out/zqlite/src/table-source.d.ts.map +1 -1
  102. package/out/zqlite/src/table-source.js +22 -17
  103. package/out/zqlite/src/table-source.js.map +1 -1
  104. package/package.json +1 -1
  105. package/out/zql/src/ivm/connection-index.d.ts +0 -68
  106. package/out/zql/src/ivm/connection-index.d.ts.map +0 -1
  107. package/out/zql/src/ivm/connection-index.js +0 -149
  108. package/out/zql/src/ivm/connection-index.js.map +0 -1
@@ -6,5 +6,4 @@ export declare class Centroid {
6
6
  }
7
7
  /** CentroidList is sorted by the mean of the centroid, ascending. */
8
8
  export type CentroidList = Centroid[];
9
- export declare function sortCentroidList(centroids: CentroidList): void;
10
9
  //# sourceMappingURL=centroid.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"centroid.d.ts","sourceRoot":"","sources":["../../../../shared/src/centroid.ts"],"names":[],"mappings":"AAIA,qBAAa,QAAQ;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAGvC;IAED,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAWrB;CACF;AAED,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG,QAAQ,EAAE,CAAC;AAEtC,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI,CAE9D"}
1
+ {"version":3,"file":"centroid.d.ts","sourceRoot":"","sources":["../../../../shared/src/centroid.ts"],"names":[],"mappings":"AAIA,qBAAa,QAAQ;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAGvC;IAED,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAWrB;CACF;AAED,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG,QAAQ,EAAE,CAAC"}
@@ -17,10 +17,7 @@ var Centroid = class {
17
17
  }
18
18
  }
19
19
  };
20
- function sortCentroidList(centroids) {
21
- centroids.sort((a, b) => a.mean - b.mean);
22
- }
23
20
  //#endregion
24
- export { Centroid, sortCentroidList };
21
+ export { Centroid };
25
22
 
26
23
  //# sourceMappingURL=centroid.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"centroid.js","names":[],"sources":["../../../../shared/src/centroid.ts"],"sourcesContent":["// Apache License 2.0\n// https://github.com/influxdata/tdigest\n\n// Centroid average position of all points in a shape\nexport class Centroid {\n mean: number;\n weight: number;\n\n constructor(mean: number, weight: number) {\n this.mean = mean;\n this.weight = weight;\n }\n\n add(r: Centroid): void {\n if (r.weight < 0) {\n throw new Error('centroid weight cannot be less than zero');\n }\n if (this.weight !== 0) {\n this.weight += r.weight;\n this.mean += (r.weight * (r.mean - this.mean)) / this.weight;\n } else {\n this.weight = r.weight;\n this.mean = r.mean;\n }\n }\n}\n\n/** CentroidList is sorted by the mean of the centroid, ascending. */\nexport type CentroidList = Centroid[];\n\nexport function sortCentroidList(centroids: CentroidList): void {\n centroids.sort((a, b) => a.mean - b.mean);\n}\n"],"mappings":";AAIA,IAAa,WAAb,MAAsB;CACpB;CACA;CAEA,YAAY,MAAc,QAAgB;EACxC,KAAK,OAAO;EACZ,KAAK,SAAS;CAChB;CAEA,IAAI,GAAmB;EACrB,IAAI,EAAE,SAAS,GACb,MAAM,IAAI,MAAM,0CAA0C;EAE5D,IAAI,KAAK,WAAW,GAAG;GACrB,KAAK,UAAU,EAAE;GACjB,KAAK,QAAS,EAAE,UAAU,EAAE,OAAO,KAAK,QAAS,KAAK;EACxD,OAAO;GACL,KAAK,SAAS,EAAE;GAChB,KAAK,OAAO,EAAE;EAChB;CACF;AACF;AAKA,SAAgB,iBAAiB,WAA+B;CAC9D,UAAU,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI;AAC1C"}
1
+ {"version":3,"file":"centroid.js","names":[],"sources":["../../../../shared/src/centroid.ts"],"sourcesContent":["// Apache License 2.0\n// https://github.com/influxdata/tdigest\n\n// Centroid average position of all points in a shape\nexport class Centroid {\n mean: number;\n weight: number;\n\n constructor(mean: number, weight: number) {\n this.mean = mean;\n this.weight = weight;\n }\n\n add(r: Centroid): void {\n if (r.weight < 0) {\n throw new Error('centroid weight cannot be less than zero');\n }\n if (this.weight !== 0) {\n this.weight += r.weight;\n this.mean += (r.weight * (r.mean - this.mean)) / this.weight;\n } else {\n this.weight = r.weight;\n this.mean = r.mean;\n }\n }\n}\n\n/** CentroidList is sorted by the mean of the centroid, ascending. */\nexport type CentroidList = Centroid[];\n"],"mappings":";AAIA,IAAa,WAAb,MAAsB;CACpB;CACA;CAEA,YAAY,MAAc,QAAgB;EACxC,KAAK,OAAO;EACZ,KAAK,SAAS;CAChB;CAEA,IAAI,GAAmB;EACrB,IAAI,EAAE,SAAS,GACb,MAAM,IAAI,MAAM,0CAA0C;EAE5D,IAAI,KAAK,WAAW,GAAG;GACrB,KAAK,UAAU,EAAE;GACjB,KAAK,QAAS,EAAE,UAAU,EAAE,OAAO,KAAK,QAAS,KAAK;EACxD,OAAO;GACL,KAAK,SAAS,EAAE;GAChB,KAAK,OAAO,EAAE;EAChB;CACF;AACF"}
@@ -8,6 +8,12 @@ export interface ReadonlyTDigest {
8
8
  export declare class TDigest {
9
9
  #private;
10
10
  readonly compression: number;
11
+ /**
12
+ * A digest keeps roughly `compression` centroids, and buffers up to eight
13
+ * times as many values between merges. The Go original defaults to 1000;
14
+ * 100 keeps p50, p95 and p99 within about 0.5% for a tenth of the memory
15
+ * and serialized size, which is plenty for the inspector's percentiles.
16
+ */
11
17
  constructor(compression?: number);
12
18
  /**
13
19
  * fromJSON creates a TDigest from a JSON-serializable representation.
@@ -15,6 +21,10 @@ export declare class TDigest {
15
21
  */
16
22
  static fromJSON(data: Readonly<TDigestJSON>): TDigest;
17
23
  reset(): void;
24
+ /**
25
+ * Adds a value with the given weight.
26
+ * Weights which are not a number or are <= 0 are ignored, as are NaN means.
27
+ */
18
28
  add(mean: number, weight?: number): void;
19
29
  /** AddCentroidList can quickly add multiple centroids. */
20
30
  addCentroidList(centroidList: CentroidList): void;
@@ -1 +1 @@
1
- {"version":3,"file":"tdigest.d.ts","sourceRoot":"","sources":["../../../../shared/src/tdigest.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,QAAQ,EAAoB,KAAK,YAAY,EAAC,MAAM,eAAe,CAAC;AAC5E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAID,qBAAa,OAAO;;IAClB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAY7B,YAAY,WAAW,GAAE,MAAa,EAKrC;IAED;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CASpD;IAED,KAAK,IAAI,IAAI,CAQZ;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,QAEnC;IAED,0DAA0D;IAC1D,eAAe,CAAC,YAAY,EAAE,YAAY,QAIzC;IAED;;;OAGG;IACH,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAmB7B;IAED;;;;QAII;IACJ,KAAK,CAAC,EAAE,EAAE,OAAO,QAGhB;IAwCD;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,GAAE,YAAiB,GAAG,YAAY,CAG7C;IAED,KAAK,IAAI,MAAM,CAMd;IAED;;;OAGG;IACH,MAAM,IAAI,WAAW,CAOpB;IA8BD,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAuC1B;IAED;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CA2ErB;CAgBF;AAID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoB3D"}
1
+ {"version":3,"file":"tdigest.d.ts","sourceRoot":"","sources":["../../../../shared/src/tdigest.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,QAAQ,EAAE,KAAK,YAAY,EAAC,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAcD,qBAAa,OAAO;;IAClB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAqB7B;;;;;OAKG;IACH,YAAY,WAAW,GAAE,MAAY,EAOpC;IAED;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CASpD;IAED,KAAK,IAAI,IAAI,CASZ;IAED;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,CAiB1C;IAED,0DAA0D;IAC1D,eAAe,CAAC,YAAY,EAAE,YAAY,QAIzC;IAED;;;OAGG;IACH,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAE7B;IAED;;;;QAII;IACJ,KAAK,CAAC,EAAE,EAAE,OAAO,QAShB;IAiHD;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,GAAE,YAAiB,GAAG,YAAY,CAO7C;IAED,KAAK,IAAI,MAAM,CAMd;IAED;;;OAGG;IACH,MAAM,IAAI,WAAW,CAOpB;IA6BD,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAqC1B;IAED;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CA2ErB;CAgBF;AAID,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoB3D"}
@@ -1,21 +1,37 @@
1
1
  import { binarySearch } from "./binary-search.js";
2
- import { Centroid, sortCentroidList } from "./centroid.js";
2
+ import { Centroid } from "./centroid.js";
3
3
  //#region ../shared/src/tdigest.ts
4
+ /** Initial capacity of the buffer of unprocessed values. */
5
+ var INITIAL_CAPACITY = 16;
4
6
  var TDigest = class TDigest {
5
7
  compression;
6
- #maxProcessed;
7
8
  #maxUnprocessed;
8
- #processed;
9
- #unprocessed;
9
+ /** Means of the processed centroids, ascending. */
10
+ #means;
11
+ /** Weights of the processed centroids, parallel to `#means`. */
12
+ #weights;
13
+ /** Means of the values added since the last `#process`, in order. */
14
+ #unprocessedMeans;
15
+ /** Weights of the unprocessed values, parallel to `#unprocessedMeans`. */
16
+ #unprocessedWeights;
17
+ #unprocessedCount;
10
18
  #cumulative;
11
19
  #processedWeight;
12
20
  #unprocessedWeight;
13
21
  #min;
14
22
  #max;
15
- constructor(compression = 1e3) {
23
+ /**
24
+ * A digest keeps roughly `compression` centroids, and buffers up to eight
25
+ * times as many values between merges. The Go original defaults to 1000;
26
+ * 100 keeps p50, p95 and p99 within about 0.5% for a tenth of the memory
27
+ * and serialized size, which is plenty for the inspector's percentiles.
28
+ */
29
+ constructor(compression = 100) {
16
30
  this.compression = compression;
17
- this.#maxProcessed = processedSize(0, this.compression);
18
31
  this.#maxUnprocessed = unprocessedSize(0, this.compression);
32
+ const capacity = Math.min(INITIAL_CAPACITY, this.#maxUnprocessed + 1);
33
+ this.#unprocessedMeans = new Float64Array(capacity);
34
+ this.#unprocessedWeights = new Float64Array(capacity);
19
35
  this.reset();
20
36
  }
21
37
  /**
@@ -29,30 +45,39 @@ var TDigest = class TDigest {
29
45
  return digest;
30
46
  }
31
47
  reset() {
32
- this.#processed = [];
33
- this.#unprocessed = [];
48
+ this.#means = [];
49
+ this.#weights = [];
50
+ this.#unprocessedCount = 0;
34
51
  this.#cumulative = [];
35
52
  this.#processedWeight = 0;
36
53
  this.#unprocessedWeight = 0;
37
54
  this.#min = Number.MAX_VALUE;
38
55
  this.#max = -Number.MAX_VALUE;
39
56
  }
57
+ /**
58
+ * Adds a value with the given weight.
59
+ * Weights which are not a number or are <= 0 are ignored, as are NaN means.
60
+ */
40
61
  add(mean, weight = 1) {
41
- this.addCentroid(new Centroid(mean, weight));
62
+ if (Number.isNaN(mean) || weight <= 0 || !Number.isFinite(weight)) return;
63
+ const n = this.#unprocessedCount;
64
+ if (n === this.#unprocessedMeans.length) this.#grow();
65
+ this.#unprocessedMeans[n] = mean;
66
+ this.#unprocessedWeights[n] = weight;
67
+ this.#unprocessedCount = n + 1;
68
+ this.#unprocessedWeight += weight;
69
+ if (this.#unprocessedCount > this.#maxUnprocessed) this.#process();
42
70
  }
43
71
  /** AddCentroidList can quickly add multiple centroids. */
44
72
  addCentroidList(centroidList) {
45
- for (const c of centroidList) this.addCentroid(c);
73
+ for (const c of centroidList) this.add(c.mean, c.weight);
46
74
  }
47
75
  /**
48
76
  * AddCentroid adds a single centroid.
49
77
  * Weights which are not a number or are <= 0 are ignored, as are NaN means.
50
78
  */
51
79
  addCentroid(c) {
52
- if (Number.isNaN(c.mean) || c.weight <= 0 || Number.isNaN(c.weight) || !Number.isFinite(c.weight)) return;
53
- this.#unprocessed.push(new Centroid(c.mean, c.weight));
54
- this.#unprocessedWeight += c.weight;
55
- if (this.#processed.length > this.#maxProcessed || this.#unprocessed.length > this.#maxUnprocessed) this.#process();
80
+ this.add(c.mean, c.weight);
56
81
  }
57
82
  /**
58
83
  * Merges the supplied digest into this digest. Functionally equivalent to
@@ -61,35 +86,88 @@ var TDigest = class TDigest {
61
86
  **/
62
87
  merge(t2) {
63
88
  t2.#process();
64
- this.addCentroidList(t2.#processed);
89
+ const means = t2.#means;
90
+ const weights = t2.#weights;
91
+ for (let i = 0; i < means.length; i++) this.add(means[i], weights[i]);
92
+ }
93
+ /** Doubles the unprocessed buffer, up to what `add` lets it hold. */
94
+ #grow() {
95
+ const capacity = Math.min(this.#unprocessedMeans.length * 2, this.#maxUnprocessed + 1);
96
+ const means = new Float64Array(capacity);
97
+ means.set(this.#unprocessedMeans);
98
+ this.#unprocessedMeans = means;
99
+ const weights = new Float64Array(capacity);
100
+ weights.set(this.#unprocessedWeights);
101
+ this.#unprocessedWeights = weights;
65
102
  }
103
+ /**
104
+ * Merges the unprocessed values into the centroids: walks both in order of
105
+ * mean, folding each into the last centroid while that stays within its
106
+ * size limit, and starting a new centroid otherwise.
107
+ */
66
108
  #process() {
67
- if (this.#unprocessed.length > 0 || this.#processed.length > this.#maxProcessed) {
68
- this.#unprocessed.push(...this.#processed);
69
- sortCentroidList(this.#unprocessed);
70
- this.#processed.length = 0;
71
- this.#processed.push(this.#unprocessed[0]);
72
- this.#processedWeight += this.#unprocessedWeight;
73
- this.#unprocessedWeight = 0;
74
- let soFar = this.#unprocessed[0].weight;
75
- let limit = this.#processedWeight * this.#integratedQ(1);
76
- for (let i = 1; i < this.#unprocessed.length; i++) {
77
- const centroid = this.#unprocessed[i];
78
- const projected = soFar + centroid.weight;
79
- if (projected <= limit) {
80
- soFar = projected;
81
- this.#processed.at(-1).add(centroid);
82
- } else {
83
- const k1 = this.#integratedLocation(soFar / this.#processedWeight);
84
- limit = this.#processedWeight * this.#integratedQ(k1 + 1);
85
- soFar += centroid.weight;
86
- this.#processed.push(centroid);
109
+ if (this.#unprocessedCount === 0) return;
110
+ const [newMeans, newWeights] = this.#sortedUnprocessed();
111
+ const oldMeans = this.#means;
112
+ const oldWeights = this.#weights;
113
+ const n = newMeans.length;
114
+ const p = oldMeans.length;
115
+ this.#unprocessedCount = 0;
116
+ this.#processedWeight += this.#unprocessedWeight;
117
+ this.#unprocessedWeight = 0;
118
+ const total = this.#processedWeight;
119
+ const means = [];
120
+ const weights = [];
121
+ let mean = 0;
122
+ let weight = 0;
123
+ let soFar = 0;
124
+ let limit = 0;
125
+ let i = 0;
126
+ let j = 0;
127
+ while (i < n || j < p) {
128
+ let m;
129
+ let w;
130
+ if (i < n && (j === p || newMeans[i] <= oldMeans[j])) {
131
+ m = newMeans[i];
132
+ w = newWeights[i++];
133
+ } else {
134
+ m = oldMeans[j];
135
+ w = oldWeights[j++];
136
+ }
137
+ if (soFar + w <= limit) {
138
+ weight += w;
139
+ mean += w * (m - mean) / weight;
140
+ } else {
141
+ if (weight > 0) {
142
+ means.push(mean);
143
+ weights.push(weight);
87
144
  }
145
+ const k = this.#integratedLocation(soFar / total);
146
+ limit = total * this.#integratedQ(k + 1);
147
+ mean = m;
148
+ weight = w;
88
149
  }
89
- this.#min = Math.min(this.#min, this.#processed[0].mean);
90
- this.#max = Math.max(this.#max, this.#processed.at(-1).mean);
91
- this.#unprocessed.length = 0;
150
+ soFar += w;
151
+ }
152
+ means.push(mean);
153
+ weights.push(weight);
154
+ this.#means = means;
155
+ this.#weights = weights;
156
+ this.#min = Math.min(this.#min, means[0]);
157
+ this.#max = Math.max(this.#max, means.at(-1));
158
+ }
159
+ /** The unprocessed means and weights, sorted by mean. */
160
+ #sortedUnprocessed() {
161
+ const n = this.#unprocessedCount;
162
+ const means = this.#unprocessedMeans.subarray(0, n);
163
+ const weights = this.#unprocessedWeights.subarray(0, n);
164
+ if (isSorted(means)) return [means, weights];
165
+ if (allEqual(weights)) {
166
+ means.sort();
167
+ return [means, weights];
92
168
  }
169
+ const order = Array.from(means, (_, k) => k).sort((a, b) => means[a] - means[b]);
170
+ return [Float64Array.from(order, (k) => means[k]), Float64Array.from(order, (k) => weights[k])];
93
171
  }
94
172
  /**
95
173
  * Centroids returns a copy of processed centroids.
@@ -100,7 +178,9 @@ var TDigest = class TDigest {
100
178
  */
101
179
  centroids(cl = []) {
102
180
  this.#process();
103
- return [...cl, ...this.#processed];
181
+ const result = [...cl];
182
+ for (let i = 0; i < this.#means.length; i++) result.push(new Centroid(this.#means[i], this.#weights[i]));
183
+ return result;
104
184
  }
105
185
  count() {
106
186
  this.#process();
@@ -113,37 +193,37 @@ var TDigest = class TDigest {
113
193
  toJSON() {
114
194
  this.#process();
115
195
  const data = [this.compression];
116
- for (const centroid of this.#processed) data.push(centroid.mean, centroid.weight);
196
+ for (let i = 0; i < this.#means.length; i++) data.push(this.#means[i], this.#weights[i]);
117
197
  return data;
118
198
  }
119
199
  #updateCumulative() {
120
200
  if (this.#cumulative.length > 0 && this.#cumulative.at(-1) === this.#processedWeight) return;
121
- const n = this.#processed.length + 1;
201
+ const n = this.#means.length + 1;
122
202
  if (this.#cumulative.length > n) this.#cumulative.length = n;
123
203
  let prev = 0;
124
- for (let i = 0; i < this.#processed.length; i++) {
125
- const cur = this.#processed[i].weight;
204
+ for (let i = 0; i < this.#means.length; i++) {
205
+ const cur = this.#weights[i];
126
206
  this.#cumulative[i] = prev + cur / 2;
127
207
  prev += cur;
128
208
  }
129
- this.#cumulative[this.#processed.length] = prev;
209
+ this.#cumulative[this.#means.length] = prev;
130
210
  }
131
211
  quantile(q) {
132
212
  this.#process();
133
213
  this.#updateCumulative();
134
- if (q < 0 || q > 1 || this.#processed.length === 0) return NaN;
135
- if (this.#processed.length === 1) return this.#processed[0].mean;
214
+ if (q < 0 || q > 1 || this.#means.length === 0) return NaN;
215
+ if (this.#means.length === 1) return this.#means[0];
136
216
  const index = q * this.#processedWeight;
137
- if (index <= this.#processed[0].weight / 2) return this.#min + 2 * index / this.#processed[0].weight * (this.#processed[0].mean - this.#min);
217
+ if (index <= this.#weights[0] / 2) return this.#min + 2 * index / this.#weights[0] * (this.#means[0] - this.#min);
138
218
  const lower = binarySearch(this.#cumulative.length, (i) => -this.#cumulative[i] + index);
139
219
  if (lower + 1 !== this.#cumulative.length) {
140
220
  const z1 = index - this.#cumulative[lower - 1];
141
221
  const z2 = this.#cumulative[lower] - index;
142
- return weightedAverage(this.#processed[lower - 1].mean, z2, this.#processed[lower].mean, z1);
222
+ return weightedAverage(this.#means[lower - 1], z2, this.#means[lower], z1);
143
223
  }
144
- const z1 = index - this.#processedWeight - this.#processed[lower - 1].weight / 2;
145
- const z2 = this.#processed[lower - 1].weight / 2 - z1;
146
- return weightedAverage(this.#processed.at(-1).mean, z1, this.#max, z2);
224
+ const z1 = index - this.#processedWeight - this.#weights[lower - 1] / 2;
225
+ const z2 = this.#weights[lower - 1] / 2 - z1;
226
+ return weightedAverage(this.#means.at(-1), z1, this.#max, z2);
147
227
  }
148
228
  /**
149
229
  * CDF returns the cumulative distribution function for a given value x.
@@ -151,7 +231,7 @@ var TDigest = class TDigest {
151
231
  cdf(x) {
152
232
  this.#process();
153
233
  this.#updateCumulative();
154
- switch (this.#processed.length) {
234
+ switch (this.#means.length) {
155
235
  case 0: return 0;
156
236
  case 1: {
157
237
  const width = this.#max - this.#min;
@@ -163,19 +243,19 @@ var TDigest = class TDigest {
163
243
  }
164
244
  if (x <= this.#min) return 0;
165
245
  if (x >= this.#max) return 1;
166
- const m0 = this.#processed[0].mean;
246
+ const m0 = this.#means[0];
167
247
  if (x <= m0) {
168
- if (m0 - this.#min > 0) return (x - this.#min) / (m0 - this.#min) * this.#processed[0].weight / this.#processedWeight / 2;
248
+ if (m0 - this.#min > 0) return (x - this.#min) / (m0 - this.#min) * this.#weights[0] / this.#processedWeight / 2;
169
249
  return 0;
170
250
  }
171
- const mn = this.#processed.at(-1).mean;
251
+ const mn = this.#means.at(-1);
172
252
  if (x >= mn) {
173
- if (this.#max - mn > 0) return 1 - (this.#max - x) / (this.#max - mn) * this.#processed.at(-1).weight / this.#processedWeight / 2;
253
+ if (this.#max - mn > 0) return 1 - (this.#max - x) / (this.#max - mn) * this.#weights.at(-1) / this.#processedWeight / 2;
174
254
  return 1;
175
255
  }
176
- const upper = binarySearch(this.#processed.length, (i) => x - this.#processed[i].mean || 1);
177
- const z1 = x - this.#processed[upper - 1].mean;
178
- const z2 = this.#processed[upper].mean - x;
256
+ const upper = binarySearch(this.#means.length, (i) => x - this.#means[i] || 1);
257
+ const z1 = x - this.#means[upper - 1];
258
+ const z2 = this.#means[upper] - x;
179
259
  return weightedAverage(this.#cumulative[upper - 1], z2, this.#cumulative[upper], z1) / this.#processedWeight;
180
260
  }
181
261
  #integratedQ(k) {
@@ -185,6 +265,14 @@ var TDigest = class TDigest {
185
265
  return this.compression * (Math.asin(2 * q - 1) + Math.PI / 2) / Math.PI;
186
266
  }
187
267
  };
268
+ function isSorted(values) {
269
+ for (let i = 1; i < values.length; i++) if (values[i] < values[i - 1]) return false;
270
+ return true;
271
+ }
272
+ function allEqual(values) {
273
+ for (let i = 1; i < values.length; i++) if (values[i] !== values[0]) return false;
274
+ return true;
275
+ }
188
276
  function weightedAverage(x1, w1, x2, w2) {
189
277
  if (x1 <= x2) return weightedAverageSorted(x1, w1, x2, w2);
190
278
  return weightedAverageSorted(x2, w2, x1, w1);
@@ -193,10 +281,6 @@ function weightedAverageSorted(x1, w1, x2, w2) {
193
281
  const x = (x1 * w1 + x2 * w2) / (w1 + w2);
194
282
  return Math.max(x1, Math.min(x, x2));
195
283
  }
196
- function processedSize(size, compression) {
197
- if (size === 0) return Math.ceil(compression) * 2;
198
- return size;
199
- }
200
284
  function unprocessedSize(size, compression) {
201
285
  if (size === 0) return Math.ceil(compression) * 8;
202
286
  return size;
@@ -1 +1 @@
1
- {"version":3,"file":"tdigest.js","names":["#maxProcessed","#maxUnprocessed","#processed","#unprocessed","#cumulative","#processedWeight","#unprocessedWeight","#min","#max","#process","#integratedQ","#integratedLocation","#updateCumulative"],"sources":["../../../../shared/src/tdigest.ts"],"sourcesContent":["// Apache License 2.0\n// https://github.com/influxdata/tdigest\n\nimport {binarySearch} from './binary-search.ts';\nimport {Centroid, sortCentroidList, type CentroidList} from './centroid.ts';\nimport type {TDigestJSON} from './tdigest-schema.ts';\n\nexport interface ReadonlyTDigest {\n readonly count: () => number;\n readonly quantile: (q: number) => number;\n readonly cdf: (x: number) => number;\n}\n\n// TDigest is a data structure for accurate on-line accumulation of\n// rank-based statistics such as quantiles and trimmed means.\nexport class TDigest {\n readonly compression: number;\n\n #maxProcessed: number;\n #maxUnprocessed: number;\n #processed!: CentroidList;\n #unprocessed!: CentroidList;\n #cumulative!: number[];\n #processedWeight!: number;\n #unprocessedWeight!: number;\n #min!: number;\n #max!: number;\n\n constructor(compression: number = 1000) {\n this.compression = compression;\n this.#maxProcessed = processedSize(0, this.compression);\n this.#maxUnprocessed = unprocessedSize(0, this.compression);\n this.reset();\n }\n\n /**\n * fromJSON creates a TDigest from a JSON-serializable representation.\n * The data should be an object with compression and centroids array.\n */\n static fromJSON(data: Readonly<TDigestJSON>): TDigest {\n const digest = new TDigest(data[0]);\n if (data.length % 2 !== 1) {\n throw new Error('Invalid centroids array');\n }\n for (let i = 1; i < data.length; i += 2) {\n digest.add(data[i], data[i + 1]);\n }\n return digest;\n }\n\n reset(): void {\n this.#processed = [];\n this.#unprocessed = [];\n this.#cumulative = [];\n this.#processedWeight = 0;\n this.#unprocessedWeight = 0;\n this.#min = Number.MAX_VALUE;\n this.#max = -Number.MAX_VALUE;\n }\n\n add(mean: number, weight: number = 1) {\n this.addCentroid(new Centroid(mean, weight));\n }\n\n /** AddCentroidList can quickly add multiple centroids. */\n addCentroidList(centroidList: CentroidList) {\n for (const c of centroidList) {\n this.addCentroid(c);\n }\n }\n\n /**\n * AddCentroid adds a single centroid.\n * Weights which are not a number or are <= 0 are ignored, as are NaN means.\n */\n addCentroid(c: Centroid): void {\n if (\n Number.isNaN(c.mean) ||\n c.weight <= 0 ||\n Number.isNaN(c.weight) ||\n !Number.isFinite(c.weight)\n ) {\n return;\n }\n\n this.#unprocessed.push(new Centroid(c.mean, c.weight));\n this.#unprocessedWeight += c.weight;\n\n if (\n this.#processed.length > this.#maxProcessed ||\n this.#unprocessed.length > this.#maxUnprocessed\n ) {\n this.#process();\n }\n }\n\n /**\n * Merges the supplied digest into this digest. Functionally equivalent to\n * calling t.AddCentroidList(t2.Centroids(nil)), but avoids making an extra\n * copy of the CentroidList.\n **/\n merge(t2: TDigest) {\n t2.#process();\n this.addCentroidList(t2.#processed);\n }\n\n #process() {\n if (\n this.#unprocessed.length > 0 ||\n this.#processed.length > this.#maxProcessed\n ) {\n // Append all processed centroids to the unprocessed list and sort\n this.#unprocessed.push(...this.#processed);\n sortCentroidList(this.#unprocessed);\n\n // Reset processed list with first centroid\n this.#processed.length = 0;\n this.#processed.push(this.#unprocessed[0]);\n\n this.#processedWeight += this.#unprocessedWeight;\n this.#unprocessedWeight = 0;\n let soFar = this.#unprocessed[0].weight;\n let limit = this.#processedWeight * this.#integratedQ(1);\n for (let i = 1; i < this.#unprocessed.length; i++) {\n const centroid = this.#unprocessed[i];\n const projected = soFar + centroid.weight;\n if (projected <= limit) {\n soFar = projected;\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#processed.at(-1)!.add(centroid);\n } else {\n const k1 = this.#integratedLocation(soFar / this.#processedWeight);\n limit = this.#processedWeight * this.#integratedQ(k1 + 1);\n soFar += centroid.weight;\n this.#processed.push(centroid);\n }\n }\n this.#min = Math.min(this.#min, this.#processed[0].mean);\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#max = Math.max(this.#max, this.#processed.at(-1)!.mean);\n this.#unprocessed.length = 0;\n }\n }\n\n /**\n * Centroids returns a copy of processed centroids.\n * Useful when aggregating multiple t-digests.\n *\n * Centroids are appended to the passed CentroidList; if you're re-using a\n * buffer, be sure to pass cl[:0].\n */\n centroids(cl: CentroidList = []): CentroidList {\n this.#process();\n return [...cl, ...this.#processed];\n }\n\n count(): number {\n this.#process();\n\n // this.process always updates this.processedWeight to the total count of all\n // centroids, so we don't need to re-count here.\n return this.#processedWeight;\n }\n\n /**\n * toJSON returns a JSON-serializable representation of the digest.\n * This processes the digest and returns an object with compression and centroid data.\n */\n toJSON(): TDigestJSON {\n this.#process();\n const data: TDigestJSON = [this.compression];\n for (const centroid of this.#processed) {\n data.push(centroid.mean, centroid.weight);\n }\n return data;\n }\n\n #updateCumulative() {\n // Weight can only increase, so the final cumulative value will always be\n // either equal to, or less than, the total weight. If they are the same,\n // then nothing has changed since the last update.\n if (\n this.#cumulative.length > 0 &&\n this.#cumulative.at(-1) === this.#processedWeight\n ) {\n return;\n }\n const n = this.#processed.length + 1;\n if (this.#cumulative.length > n) {\n this.#cumulative.length = n;\n }\n\n let prev = 0;\n for (let i = 0; i < this.#processed.length; i++) {\n const centroid = this.#processed[i];\n const cur = centroid.weight;\n this.#cumulative[i] = prev + cur / 2;\n prev += cur;\n }\n this.#cumulative[this.#processed.length] = prev;\n }\n\n // Quantile returns the (approximate) quantile of\n // the distribution. Accepted values for q are between 0 and 1.\n // Returns NaN if Count is zero or bad inputs.\n quantile(q: number): number {\n this.#process();\n this.#updateCumulative();\n if (q < 0 || q > 1 || this.#processed.length === 0) {\n return NaN;\n }\n if (this.#processed.length === 1) {\n return this.#processed[0].mean;\n }\n const index = q * this.#processedWeight;\n if (index <= this.#processed[0].weight / 2) {\n return (\n this.#min +\n ((2 * index) / this.#processed[0].weight) *\n (this.#processed[0].mean - this.#min)\n );\n }\n\n const lower = binarySearch(\n this.#cumulative.length,\n (i: number) => -this.#cumulative[i] + index,\n );\n\n if (lower + 1 !== this.#cumulative.length) {\n const z1 = index - this.#cumulative[lower - 1];\n const z2 = this.#cumulative[lower] - index;\n return weightedAverage(\n this.#processed[lower - 1].mean,\n z2,\n this.#processed[lower].mean,\n z1,\n );\n }\n\n const z1 =\n index - this.#processedWeight - this.#processed[lower - 1].weight / 2;\n const z2 = this.#processed[lower - 1].weight / 2 - z1;\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return weightedAverage(this.#processed.at(-1)!.mean, z1, this.#max, z2);\n }\n\n /**\n * CDF returns the cumulative distribution function for a given value x.\n */\n cdf(x: number): number {\n this.#process();\n this.#updateCumulative();\n switch (this.#processed.length) {\n case 0:\n return 0;\n case 1: {\n const width = this.#max - this.#min;\n if (x <= this.#min) {\n return 0;\n }\n if (x >= this.#max) {\n return 1;\n }\n if (x - this.#min <= width) {\n // min and max are too close together to do any viable interpolation\n return 0.5;\n }\n return (x - this.#min) / width;\n }\n }\n\n if (x <= this.#min) {\n return 0;\n }\n if (x >= this.#max) {\n return 1;\n }\n const m0 = this.#processed[0].mean;\n // Left Tail\n if (x <= m0) {\n if (m0 - this.#min > 0) {\n return (\n (((x - this.#min) / (m0 - this.#min)) * this.#processed[0].weight) /\n this.#processedWeight /\n 2\n );\n }\n return 0;\n }\n // Right Tail\n // oxlint-disable-next-line typescript/no-non-null-assertion\n const mn = this.#processed.at(-1)!.mean;\n if (x >= mn) {\n if (this.#max - mn > 0) {\n return (\n 1 -\n (((this.#max - x) / (this.#max - mn)) *\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#processed.at(-1)!.weight) /\n this.#processedWeight /\n 2\n );\n }\n return 1;\n }\n\n const upper = binarySearch(\n this.#processed.length,\n // Treat equals as greater than, so we can use the upper index\n // This is equivalent to:\n // i => this.#processed[i].mean > x ? -1 : 1,\n i => x - this.#processed[i].mean || 1,\n );\n\n const z1 = x - this.#processed[upper - 1].mean;\n const z2 = this.#processed[upper].mean - x;\n return (\n weightedAverage(\n this.#cumulative[upper - 1],\n z2,\n this.#cumulative[upper],\n z1,\n ) / this.#processedWeight\n );\n }\n\n #integratedQ(k: number): number {\n return (\n (Math.sin(\n (Math.min(k, this.compression) * Math.PI) / this.compression -\n Math.PI / 2,\n ) +\n 1) /\n 2\n );\n }\n\n #integratedLocation(q: number): number {\n return (this.compression * (Math.asin(2 * q - 1) + Math.PI / 2)) / Math.PI;\n }\n}\n\n// Calculate number of bytes needed for a tdigest of size c,\n// where c is the compression value\nexport function byteSizeForCompression(comp: number): number {\n const c = comp | 0;\n // // A centroid is 2 float64s, so we need 16 bytes for each centroid\n // float_size := 8\n // centroid_size := 2 * float_size\n\n // // Unprocessed and processed can grow up to length c\n // unprocessed_size := centroid_size * c\n // processed_size := unprocessed_size\n\n // // the cumulative field can also be of length c, but each item is a single float64\n // cumulative_size := float_size * c // <- this could also be unprocessed_size / 2\n\n // return unprocessed_size + processed_size + cumulative_size\n\n // // or, more succinctly:\n // return float_size * c * 5\n\n // or even more succinctly\n return c * 40;\n}\n\nfunction weightedAverage(\n x1: number,\n w1: number,\n x2: number,\n w2: number,\n): number {\n if (x1 <= x2) {\n return weightedAverageSorted(x1, w1, x2, w2);\n }\n return weightedAverageSorted(x2, w2, x1, w1);\n}\n\nfunction weightedAverageSorted(\n x1: number,\n w1: number,\n x2: number,\n w2: number,\n): number {\n const x = (x1 * w1 + x2 * w2) / (w1 + w2);\n return Math.max(x1, Math.min(x, x2));\n}\n\nfunction processedSize(size: number, compression: number): number {\n if (size === 0) {\n return Math.ceil(compression) * 2;\n }\n return size;\n}\n\nfunction unprocessedSize(size: number, compression: number): number {\n if (size === 0) {\n return Math.ceil(compression) * 8;\n }\n return size;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tdigest.js","names":["#maxUnprocessed","#unprocessedMeans","#unprocessedWeights","#means","#weights","#unprocessedCount","#cumulative","#processedWeight","#unprocessedWeight","#min","#max","#grow","#process","#sortedUnprocessed","#integratedLocation","#integratedQ","#updateCumulative"],"sources":["../../../../shared/src/tdigest.ts"],"sourcesContent":["// Apache License 2.0\n// https://github.com/influxdata/tdigest\n\nimport {binarySearch} from './binary-search.ts';\nimport {Centroid, type CentroidList} from './centroid.ts';\nimport type {TDigestJSON} from './tdigest-schema.ts';\n\nexport interface ReadonlyTDigest {\n readonly count: () => number;\n readonly quantile: (q: number) => number;\n readonly cdf: (x: number) => number;\n}\n\n/** Initial capacity of the buffer of unprocessed values. */\nconst INITIAL_CAPACITY = 16;\n\n// TDigest is a data structure for accurate on-line accumulation of\n// rank-based statistics such as quantiles and trimmed means.\n//\n// Unlike the Go original, centroids are kept as parallel arrays of means and\n// weights rather than as objects, so adding a value allocates nothing. New\n// values are buffered in a Float64Array and sorted with its native numeric\n// sort instead of Array.prototype.sort with a comparator. On an engine\n// without a JIT, such as Hermes in React Native, calling the comparator for\n// every comparison is what made adding values expensive.\nexport class TDigest {\n readonly compression: number;\n\n readonly #maxUnprocessed: number;\n\n /** Means of the processed centroids, ascending. */\n #means!: number[];\n /** Weights of the processed centroids, parallel to `#means`. */\n #weights!: number[];\n\n /** Means of the values added since the last `#process`, in order. */\n #unprocessedMeans: Float64Array;\n /** Weights of the unprocessed values, parallel to `#unprocessedMeans`. */\n #unprocessedWeights: Float64Array;\n #unprocessedCount!: number;\n\n #cumulative!: number[];\n #processedWeight!: number;\n #unprocessedWeight!: number;\n #min!: number;\n #max!: number;\n\n /**\n * A digest keeps roughly `compression` centroids, and buffers up to eight\n * times as many values between merges. The Go original defaults to 1000;\n * 100 keeps p50, p95 and p99 within about 0.5% for a tenth of the memory\n * and serialized size, which is plenty for the inspector's percentiles.\n */\n constructor(compression: number = 100) {\n this.compression = compression;\n this.#maxUnprocessed = unprocessedSize(0, this.compression);\n const capacity = Math.min(INITIAL_CAPACITY, this.#maxUnprocessed + 1);\n this.#unprocessedMeans = new Float64Array(capacity);\n this.#unprocessedWeights = new Float64Array(capacity);\n this.reset();\n }\n\n /**\n * fromJSON creates a TDigest from a JSON-serializable representation.\n * The data should be an object with compression and centroids array.\n */\n static fromJSON(data: Readonly<TDigestJSON>): TDigest {\n const digest = new TDigest(data[0]);\n if (data.length % 2 !== 1) {\n throw new Error('Invalid centroids array');\n }\n for (let i = 1; i < data.length; i += 2) {\n digest.add(data[i], data[i + 1]);\n }\n return digest;\n }\n\n reset(): void {\n this.#means = [];\n this.#weights = [];\n this.#unprocessedCount = 0;\n this.#cumulative = [];\n this.#processedWeight = 0;\n this.#unprocessedWeight = 0;\n this.#min = Number.MAX_VALUE;\n this.#max = -Number.MAX_VALUE;\n }\n\n /**\n * Adds a value with the given weight.\n * Weights which are not a number or are <= 0 are ignored, as are NaN means.\n */\n add(mean: number, weight: number = 1): void {\n if (Number.isNaN(mean) || weight <= 0 || !Number.isFinite(weight)) {\n return;\n }\n\n const n = this.#unprocessedCount;\n if (n === this.#unprocessedMeans.length) {\n this.#grow();\n }\n this.#unprocessedMeans[n] = mean;\n this.#unprocessedWeights[n] = weight;\n this.#unprocessedCount = n + 1;\n this.#unprocessedWeight += weight;\n\n if (this.#unprocessedCount > this.#maxUnprocessed) {\n this.#process();\n }\n }\n\n /** AddCentroidList can quickly add multiple centroids. */\n addCentroidList(centroidList: CentroidList) {\n for (const c of centroidList) {\n this.add(c.mean, c.weight);\n }\n }\n\n /**\n * AddCentroid adds a single centroid.\n * Weights which are not a number or are <= 0 are ignored, as are NaN means.\n */\n addCentroid(c: Centroid): void {\n this.add(c.mean, c.weight);\n }\n\n /**\n * Merges the supplied digest into this digest. Functionally equivalent to\n * calling t.AddCentroidList(t2.Centroids(nil)), but avoids making an extra\n * copy of the CentroidList.\n **/\n merge(t2: TDigest) {\n t2.#process();\n // #process replaces the arrays rather than changing them, so these stay\n // intact even if t2 is this digest.\n const means = t2.#means;\n const weights = t2.#weights;\n for (let i = 0; i < means.length; i++) {\n this.add(means[i], weights[i]);\n }\n }\n\n /** Doubles the unprocessed buffer, up to what `add` lets it hold. */\n #grow(): void {\n const capacity = Math.min(\n this.#unprocessedMeans.length * 2,\n this.#maxUnprocessed + 1,\n );\n const means = new Float64Array(capacity);\n means.set(this.#unprocessedMeans);\n this.#unprocessedMeans = means;\n const weights = new Float64Array(capacity);\n weights.set(this.#unprocessedWeights);\n this.#unprocessedWeights = weights;\n }\n\n /**\n * Merges the unprocessed values into the centroids: walks both in order of\n * mean, folding each into the last centroid while that stays within its\n * size limit, and starting a new centroid otherwise.\n */\n #process() {\n if (this.#unprocessedCount === 0) {\n return;\n }\n const [newMeans, newWeights] = this.#sortedUnprocessed();\n const oldMeans = this.#means;\n const oldWeights = this.#weights;\n const n = newMeans.length;\n const p = oldMeans.length;\n this.#unprocessedCount = 0;\n this.#processedWeight += this.#unprocessedWeight;\n this.#unprocessedWeight = 0;\n const total = this.#processedWeight;\n\n const means: number[] = [];\n const weights: number[] = [];\n // The centroid being built, kept in locals rather than in the arrays,\n // which is markedly faster without a JIT. Its weight is 0 until the first\n // value.\n let mean = 0;\n let weight = 0;\n let soFar = 0;\n // A limit of 0 makes the first value start a centroid, whose limit then\n // comes from the same formula as every other's. With soFar at 0 that is\n // integratedQ(1): integratedLocation(0) is exactly 0, since\n // Math.asin(-1) is -Math.PI / 2.\n let limit = 0;\n let i = 0;\n let j = 0;\n while (i < n || j < p) {\n // On a tie the new value goes first, as in the original, which appended\n // the old centroids to the new values and sorted them with a stable sort.\n let m: number;\n let w: number;\n if (i < n && (j === p || newMeans[i] <= oldMeans[j])) {\n m = newMeans[i];\n w = newWeights[i++];\n } else {\n m = oldMeans[j];\n w = oldWeights[j++];\n }\n if (soFar + w <= limit) {\n // Same arithmetic as Centroid.add.\n weight += w;\n mean += (w * (m - mean)) / weight;\n } else {\n if (weight > 0) {\n means.push(mean);\n weights.push(weight);\n }\n const k = this.#integratedLocation(soFar / total);\n limit = total * this.#integratedQ(k + 1);\n mean = m;\n weight = w;\n }\n soFar += w;\n }\n means.push(mean);\n weights.push(weight);\n\n this.#means = means;\n this.#weights = weights;\n this.#min = Math.min(this.#min, means[0]);\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#max = Math.max(this.#max, means.at(-1)!);\n }\n\n /** The unprocessed means and weights, sorted by mean. */\n #sortedUnprocessed(): [Float64Array, Float64Array] {\n const n = this.#unprocessedCount;\n const means = this.#unprocessedMeans.subarray(0, n);\n const weights = this.#unprocessedWeights.subarray(0, n);\n // fromJSON and merge add centroids in order of mean.\n if (isSorted(means)) {\n return [means, weights];\n }\n // With one weight for all the values, sorting the means alone keeps every\n // value with its weight, and the native numeric sort needs no comparator.\n if (allEqual(weights)) {\n means.sort();\n return [means, weights];\n }\n // A stable sort, so values with equal means stay in the order added.\n const order = Array.from(means, (_, k) => k).sort(\n (a, b) => means[a] - means[b],\n );\n return [\n Float64Array.from(order, k => means[k]),\n Float64Array.from(order, k => weights[k]),\n ];\n }\n\n /**\n * Centroids returns a copy of processed centroids.\n * Useful when aggregating multiple t-digests.\n *\n * Centroids are appended to the passed CentroidList; if you're re-using a\n * buffer, be sure to pass cl[:0].\n */\n centroids(cl: CentroidList = []): CentroidList {\n this.#process();\n const result = [...cl];\n for (let i = 0; i < this.#means.length; i++) {\n result.push(new Centroid(this.#means[i], this.#weights[i]));\n }\n return result;\n }\n\n count(): number {\n this.#process();\n\n // this.process always updates this.processedWeight to the total count of all\n // centroids, so we don't need to re-count here.\n return this.#processedWeight;\n }\n\n /**\n * toJSON returns a JSON-serializable representation of the digest.\n * This processes the digest and returns an object with compression and centroid data.\n */\n toJSON(): TDigestJSON {\n this.#process();\n const data: TDigestJSON = [this.compression];\n for (let i = 0; i < this.#means.length; i++) {\n data.push(this.#means[i], this.#weights[i]);\n }\n return data;\n }\n\n #updateCumulative() {\n // Weight can only increase, so the final cumulative value will always be\n // either equal to, or less than, the total weight. If they are the same,\n // then nothing has changed since the last update.\n if (\n this.#cumulative.length > 0 &&\n this.#cumulative.at(-1) === this.#processedWeight\n ) {\n return;\n }\n const n = this.#means.length + 1;\n if (this.#cumulative.length > n) {\n this.#cumulative.length = n;\n }\n\n let prev = 0;\n for (let i = 0; i < this.#means.length; i++) {\n const cur = this.#weights[i];\n this.#cumulative[i] = prev + cur / 2;\n prev += cur;\n }\n this.#cumulative[this.#means.length] = prev;\n }\n\n // Quantile returns the (approximate) quantile of\n // the distribution. Accepted values for q are between 0 and 1.\n // Returns NaN if Count is zero or bad inputs.\n quantile(q: number): number {\n this.#process();\n this.#updateCumulative();\n if (q < 0 || q > 1 || this.#means.length === 0) {\n return NaN;\n }\n if (this.#means.length === 1) {\n return this.#means[0];\n }\n const index = q * this.#processedWeight;\n if (index <= this.#weights[0] / 2) {\n return (\n this.#min +\n ((2 * index) / this.#weights[0]) * (this.#means[0] - this.#min)\n );\n }\n\n const lower = binarySearch(\n this.#cumulative.length,\n (i: number) => -this.#cumulative[i] + index,\n );\n\n if (lower + 1 !== this.#cumulative.length) {\n const z1 = index - this.#cumulative[lower - 1];\n const z2 = this.#cumulative[lower] - index;\n return weightedAverage(\n this.#means[lower - 1],\n z2,\n this.#means[lower],\n z1,\n );\n }\n\n const z1 = index - this.#processedWeight - this.#weights[lower - 1] / 2;\n const z2 = this.#weights[lower - 1] / 2 - z1;\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return weightedAverage(this.#means.at(-1)!, z1, this.#max, z2);\n }\n\n /**\n * CDF returns the cumulative distribution function for a given value x.\n */\n cdf(x: number): number {\n this.#process();\n this.#updateCumulative();\n switch (this.#means.length) {\n case 0:\n return 0;\n case 1: {\n const width = this.#max - this.#min;\n if (x <= this.#min) {\n return 0;\n }\n if (x >= this.#max) {\n return 1;\n }\n if (x - this.#min <= width) {\n // min and max are too close together to do any viable interpolation\n return 0.5;\n }\n return (x - this.#min) / width;\n }\n }\n\n if (x <= this.#min) {\n return 0;\n }\n if (x >= this.#max) {\n return 1;\n }\n const m0 = this.#means[0];\n // Left Tail\n if (x <= m0) {\n if (m0 - this.#min > 0) {\n return (\n (((x - this.#min) / (m0 - this.#min)) * this.#weights[0]) /\n this.#processedWeight /\n 2\n );\n }\n return 0;\n }\n // Right Tail\n // oxlint-disable-next-line typescript/no-non-null-assertion\n const mn = this.#means.at(-1)!;\n if (x >= mn) {\n if (this.#max - mn > 0) {\n return (\n 1 -\n (((this.#max - x) / (this.#max - mn)) *\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#weights.at(-1)!) /\n this.#processedWeight /\n 2\n );\n }\n return 1;\n }\n\n const upper = binarySearch(\n this.#means.length,\n // Treat equals as greater than, so we can use the upper index\n // This is equivalent to:\n // i => this.#means[i] > x ? -1 : 1,\n i => x - this.#means[i] || 1,\n );\n\n const z1 = x - this.#means[upper - 1];\n const z2 = this.#means[upper] - x;\n return (\n weightedAverage(\n this.#cumulative[upper - 1],\n z2,\n this.#cumulative[upper],\n z1,\n ) / this.#processedWeight\n );\n }\n\n #integratedQ(k: number): number {\n return (\n (Math.sin(\n (Math.min(k, this.compression) * Math.PI) / this.compression -\n Math.PI / 2,\n ) +\n 1) /\n 2\n );\n }\n\n #integratedLocation(q: number): number {\n return (this.compression * (Math.asin(2 * q - 1) + Math.PI / 2)) / Math.PI;\n }\n}\n\n// Calculate number of bytes needed for a tdigest of size c,\n// where c is the compression value\nexport function byteSizeForCompression(comp: number): number {\n const c = comp | 0;\n // // A centroid is 2 float64s, so we need 16 bytes for each centroid\n // float_size := 8\n // centroid_size := 2 * float_size\n\n // // Unprocessed and processed can grow up to length c\n // unprocessed_size := centroid_size * c\n // processed_size := unprocessed_size\n\n // // the cumulative field can also be of length c, but each item is a single float64\n // cumulative_size := float_size * c // <- this could also be unprocessed_size / 2\n\n // return unprocessed_size + processed_size + cumulative_size\n\n // // or, more succinctly:\n // return float_size * c * 5\n\n // or even more succinctly\n return c * 40;\n}\n\nfunction isSorted(values: Float64Array): boolean {\n for (let i = 1; i < values.length; i++) {\n if (values[i] < values[i - 1]) {\n return false;\n }\n }\n return true;\n}\n\nfunction allEqual(values: Float64Array): boolean {\n for (let i = 1; i < values.length; i++) {\n if (values[i] !== values[0]) {\n return false;\n }\n }\n return true;\n}\n\nfunction weightedAverage(\n x1: number,\n w1: number,\n x2: number,\n w2: number,\n): number {\n if (x1 <= x2) {\n return weightedAverageSorted(x1, w1, x2, w2);\n }\n return weightedAverageSorted(x2, w2, x1, w1);\n}\n\nfunction weightedAverageSorted(\n x1: number,\n w1: number,\n x2: number,\n w2: number,\n): number {\n const x = (x1 * w1 + x2 * w2) / (w1 + w2);\n return Math.max(x1, Math.min(x, x2));\n}\n\nfunction unprocessedSize(size: number, compression: number): number {\n if (size === 0) {\n return Math.ceil(compression) * 8;\n }\n return size;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../../z2s/src/compiler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../../z2s/src/compiler.ts"],"names":[],"mappings":"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"}
@@ -152,16 +152,20 @@ function makeCorrelator(spec, parentFields, childZqlFields) {
152
152
  }
153
153
  function simple(spec, condition, table) {
154
154
  switch (condition.op) {
155
+ case "ILIKE":
156
+ case "LIKE":
157
+ case "NOT ILIKE":
158
+ case "NOT LIKE": {
159
+ const { right } = condition;
160
+ assert(right.type === "literal", "Static parameters must be bound to a value before compiling to SQL");
161
+ return sql`${valueComparison(spec, condition.left, table, right, false)} ${sql.__dangerous__rawValue(condition.op)} ${sqlConvertSingularLiteralArg(right.value === null ? null : String(right.value))}`;
162
+ }
155
163
  case "!=":
156
164
  case "<":
157
165
  case "<=":
158
166
  case "=":
159
167
  case ">":
160
- case ">=":
161
- case "ILIKE":
162
- case "LIKE":
163
- case "NOT ILIKE":
164
- case "NOT LIKE": return sql`${valueComparison(spec, condition.left, table, condition.right, false)} ${sql.__dangerous__rawValue(condition.op)} ${valueComparison(spec, condition.right, table, condition.left, false)}`;
168
+ case ">=": return sql`${valueComparison(spec, condition.left, table, condition.right, false)} ${sql.__dangerous__rawValue(condition.op)} ${valueComparison(spec, condition.right, table, condition.left, false)}`;
165
169
  case "NOT IN":
166
170
  case "IN": return any(spec, condition, table);
167
171
  case "IS":