(points: ReadonlyArray<DataPoint>, xOffset: number)
| 96 | const isTupleDataPoint = (p: DataPoint): p is DataPointTuple => Array.isArray(p); |
| 97 | |
| 98 | const packDataPointsWithXOffset = (points: ReadonlyArray<DataPoint>, xOffset: number): Float32Array => { |
| 99 | if (!points || points.length === 0) return new Float32Array(0); |
| 100 | |
| 101 | const buffer = new ArrayBuffer(points.length * 2 * 4); |
| 102 | const f32 = new Float32Array(buffer); |
| 103 | |
| 104 | // Hot path: keep logic minimal (validation happens elsewhere in option resolution). |
| 105 | for (let i = 0; i < points.length; i++) { |
| 106 | const p = points[i]!; |
| 107 | const x = isTupleDataPoint(p) ? p[0] : p.x; |
| 108 | const y = isTupleDataPoint(p) ? p[1] : p.y; |
| 109 | |
| 110 | // Subtracting before the Float32 cast preserves sub-ULP deltas for large x magnitudes. |
| 111 | f32[i * 2 + 0] = x - xOffset; |
| 112 | f32[i * 2 + 1] = y; |
| 113 | } |
| 114 | |
| 115 | return f32; |
| 116 | }; |
| 117 | |
| 118 | const assertNotDisposed = (): void => { |
| 119 | if (disposed) { |
no test coverage detected