pond-ts 0.34.0 → 0.35.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/CHANGELOG.md CHANGED
@@ -8,7 +8,9 @@ The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`, and
8
8
  them all. Pre-1.0: minor bumps may include new features and type-level changes;
9
9
  patch bumps are strictly additive.
10
10
 
11
- [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.34.0...HEAD
11
+ [Unreleased]: https://github.com/pjm17971/pond-ts/compare/v0.35.0...HEAD
12
+ [0.35.0]: https://github.com/pjm17971/pond-ts/compare/v0.34.1...v0.35.0
13
+ [0.34.1]: https://github.com/pjm17971/pond-ts/compare/v0.34.0...v0.34.1
12
14
  [0.34.0]: https://github.com/pjm17971/pond-ts/compare/v0.33.0...v0.34.0
13
15
  [0.33.0]: https://github.com/pjm17971/pond-ts/compare/v0.32.0...v0.33.0
14
16
  [0.32.0]: https://github.com/pjm17971/pond-ts/compare/v0.31.2...v0.32.0
@@ -29,6 +31,46 @@ patch bumps are strictly additive.
29
31
  [0.19.0]: https://github.com/pjm17971/pond-ts/compare/v0.18.0...v0.19.0
30
32
  [0.18.0]: https://github.com/pjm17971/pond-ts/compare/v0.17.1...v0.18.0
31
33
 
34
+ ## [0.35.0] — 2026-07-02
35
+
36
+ A `@pond-ts/charts` release: per-series line dash patterns. `pond-ts`,
37
+ `@pond-ts/react`, and `@pond-ts/fit` carry no code changes — republished in
38
+ lock-step (their `pond-ts` / `@pond-ts/react` peer ranges widen to `^0.35.0`).
39
+
40
+ ### Added
41
+
42
+ - **Charts — per-series line dash (`LineStyle.dash`).** A theme's line style
43
+ accepts an optional `dash?: readonly number[]` — a px on/off pattern
44
+ (`[6, 4]` dashed, `[2, 3]` ≈ dotted; omit or `[]` = solid) applied to the
45
+ series stroke. Lets a theme set a **modeled / forecast** line (e.g. GARCH
46
+ vol) apart from an observed one at a glance. Distinct from a `GapMode`'s
47
+ inferred gap-bridge dashing (which marks *missing data*, not the whole
48
+ line). Additive: existing themes are unaffected; a solid line never touches
49
+ `setLineDash`. New `Charts/LineChart → LineStyles` story. (#313)
50
+
51
+ ## [0.34.1] — 2026-07-01
52
+
53
+ A `pond-ts` core patch: fixes a performance regression introduced in 0.34.0.
54
+ `@pond-ts/react`, `@pond-ts/charts`, and `@pond-ts/fit` carry no code
55
+ changes — republished in lock-step; their `^0.34.0` peer ranges already
56
+ admit this patch.
57
+
58
+ ### Fixed
59
+
60
+ - **`TimeSeries.fromColumns` — `number[]` column conversion was ~7-18x
61
+ slower than intended.** The `null`/`NaN`-gap parity fix in 0.34.0
62
+ converted `number[]` columns via `Float64Array.from(raw, mapFn)`.
63
+ Supplying a map function forces V8's generic iterable-protocol path even
64
+ for a plain array, dramatically slower than a manual loop into a
65
+ preallocated buffer at 100k-element scale. Found while pointing the
66
+ `pond-columnar-ingest` wire-format spike at the real published package
67
+ instead of a local build. Fixed with a manual `for` loop in both the
68
+ key-column and value-column conversion paths — no behavior change, same
69
+ gap semantics, all 12 `fromColumns` tests unchanged and green. Added
70
+ `scripts/perf-from-columns.mjs` as the durable regression benchmark.
71
+ Measured: 100k × 7 cols, `number[]` columns, dense — 21.5ms → 2.9ms.
72
+ (#311)
73
+
32
74
  ## [0.34.0] — 2026-07-01
33
75
 
34
76
  A `pond-ts` core release: the columnar/typed-array ingress driven by the
@@ -535,10 +535,22 @@ export class TimeSeries {
535
535
  if (keyRaw === undefined) {
536
536
  throw new ValidationError(`fromColumns: missing key column '${keyDef.name}'`);
537
537
  }
538
- // epoch-ms buffer; TimeKeyColumn asserts all finite.
539
- const begin = keyRaw instanceof Float64Array
540
- ? keyRaw
541
- : Float64Array.from(keyRaw, (v) => (v == null ? NaN : Number(v)));
538
+ // epoch-ms buffer; TimeKeyColumn asserts all finite. A manual loop, not
539
+ // `Float64Array.from(arr, mapFn)`: supplying a map function forces V8's
540
+ // generic iterable-protocol path even for a plain array, ~15-20x slower
541
+ // than a preallocated-buffer copy at 100k-element scale measured, not
542
+ // theoretical (see the pond-columnar-ingest spike's ingest regression).
543
+ let begin;
544
+ if (keyRaw instanceof Float64Array) {
545
+ begin = keyRaw;
546
+ }
547
+ else {
548
+ begin = new Float64Array(keyRaw.length);
549
+ for (let j = 0; j < keyRaw.length; j += 1) {
550
+ const v = keyRaw[j];
551
+ begin[j] = v == null ? NaN : Number(v);
552
+ }
553
+ }
542
554
  const count = begin.length;
543
555
  // Throws on any non-finite timestamp.
544
556
  const keys = new TimeKeyColumn(begin, count);
@@ -579,9 +591,19 @@ export class TimeSeries {
579
591
  // the `Float64Array` branch's `Number.isFinite` gap signal — the same
580
592
  // wire value would silently mean different things depending on which
581
593
  // array type decoded it.
582
- const values = raw instanceof Float64Array
583
- ? raw
584
- : Float64Array.from(raw, (v) => (v == null ? NaN : v));
594
+ // Manual loop, not `Float64Array.from(arr, mapFn)` — see the key-column
595
+ // comment above; the cost applies identically here.
596
+ let values;
597
+ if (raw instanceof Float64Array) {
598
+ values = raw;
599
+ }
600
+ else {
601
+ values = new Float64Array(count);
602
+ for (let j = 0; j < count; j += 1) {
603
+ const v = raw[j];
604
+ values[j] = v == null ? NaN : v;
605
+ }
606
+ }
585
607
  const validity = validityFromPredicate(count, (j) => Number.isFinite(values[j]));
586
608
  columnMap.set(def.name, new Float64Column(values, count, validity, validity === undefined));
587
609
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pond-ts",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "description": "TypeScript-first time series primitives",
5
5
  "license": "MIT",
6
6
  "repository": {