@elaraai/east 1.0.65 → 1.0.67
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/dist/src/builtins.d.ts +1 -1
- package/dist/src/builtins.d.ts.map +1 -1
- package/dist/src/builtins.js +165 -0
- package/dist/src/builtins.js.map +1 -1
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +642 -0
- package/dist/src/compile.js.map +1 -1
- package/dist/src/expr/index.d.ts +3 -0
- package/dist/src/expr/index.d.ts.map +1 -1
- package/dist/src/expr/libs/vector.d.ts +53 -2
- package/dist/src/expr/libs/vector.d.ts.map +1 -1
- package/dist/src/expr/libs/vector.js +96 -1
- package/dist/src/expr/libs/vector.js.map +1 -1
- package/dist/src/expr/matrix.d.ts +53 -0
- package/dist/src/expr/matrix.d.ts.map +1 -1
- package/dist/src/expr/matrix.js +119 -0
- package/dist/src/expr/matrix.js.map +1 -1
- package/dist/src/expr/vector.d.ts +217 -1
- package/dist/src/expr/vector.d.ts.map +1 -1
- package/dist/src/expr/vector.js +396 -1
- package/dist/src/expr/vector.js.map +1 -1
- package/package.json +1 -1
package/dist/src/compile.js
CHANGED
|
@@ -1363,6 +1363,40 @@ function allocateTypedArray(elementType, length) {
|
|
|
1363
1363
|
return new Uint8ClampedArray(length);
|
|
1364
1364
|
throw new Error(`Unsupported vector element type: ${elementType.type}`);
|
|
1365
1365
|
}
|
|
1366
|
+
/** Wraps to East's 64-bit Integer semantics */
|
|
1367
|
+
function wrapI64(x) {
|
|
1368
|
+
return BigInt.asIntN(64, x);
|
|
1369
|
+
}
|
|
1370
|
+
/** Throws unless the vector/matrix element type parameter is Float or Integer */
|
|
1371
|
+
function requireNumericElem(builtin, T, loc_id, source_map) {
|
|
1372
|
+
if (T.type !== "Float" && T.type !== "Integer") {
|
|
1373
|
+
throw new EastError(`${builtin} requires Float or Integer elements`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
1374
|
+
}
|
|
1375
|
+
return T.type;
|
|
1376
|
+
}
|
|
1377
|
+
/** Throws the shared length-mismatch error for elementwise vector operands */
|
|
1378
|
+
function requireSameLength(a, b, loc_id, source_map) {
|
|
1379
|
+
if (a.length !== b.length) {
|
|
1380
|
+
throw new EastError(`Vector length mismatch (${a.length} vs ${b.length})`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
/** Throws the shared dimension-mismatch error for elementwise matrix operands */
|
|
1384
|
+
function requireSameDims(a, b, loc_id, source_map) {
|
|
1385
|
+
if (a.rows !== b.rows || a.cols !== b.cols) {
|
|
1386
|
+
throw new EastError(`Matrix dimension mismatch (${a.rows}x${a.cols} vs ${b.rows}x${b.cols})`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
/** Validates the sparse-accumulator invariant: parallel lengths and strictly ascending indices */
|
|
1390
|
+
function requireSparse(ix, v, loc_id, source_map) {
|
|
1391
|
+
if (ix.length !== v.length) {
|
|
1392
|
+
throw new EastError(`Sparse index and value lengths differ (${ix.length} vs ${v.length})`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
1393
|
+
}
|
|
1394
|
+
for (let i = 1; i < ix.length; i++) {
|
|
1395
|
+
if (ix[i] <= ix[i - 1]) {
|
|
1396
|
+
throw new EastError(`Sparse index vector must be strictly ascending`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1366
1400
|
/** Creates the appropriate TypedArray for a given element type */
|
|
1367
1401
|
function createTypedArray(elementType, values) {
|
|
1368
1402
|
if (elementType.type === "Float") {
|
|
@@ -3510,6 +3544,483 @@ const builtin_evaluators = {
|
|
|
3510
3544
|
}
|
|
3511
3545
|
return acc;
|
|
3512
3546
|
},
|
|
3547
|
+
// Vector elementwise arithmetic + reductions. Reductions fold in index
|
|
3548
|
+
// order, left to right — part of the cross-runtime contract, since a
|
|
3549
|
+
// reassociated float sum gives a different last bit.
|
|
3550
|
+
VectorScale: (loc_id, source_map, _platformDef, T) => {
|
|
3551
|
+
const elem = requireNumericElem("VectorScale", T, loc_id, source_map);
|
|
3552
|
+
return (v, alpha) => {
|
|
3553
|
+
if (elem === "Float") {
|
|
3554
|
+
const result = new Float64Array(v.length);
|
|
3555
|
+
for (let i = 0; i < v.length; i++)
|
|
3556
|
+
result[i] = v[i] * alpha;
|
|
3557
|
+
return result;
|
|
3558
|
+
}
|
|
3559
|
+
const result = new BigInt64Array(v.length);
|
|
3560
|
+
for (let i = 0; i < v.length; i++)
|
|
3561
|
+
result[i] = wrapI64(v[i] * alpha);
|
|
3562
|
+
return result;
|
|
3563
|
+
};
|
|
3564
|
+
},
|
|
3565
|
+
VectorSum: (loc_id, source_map, _platformDef, T) => {
|
|
3566
|
+
const elem = requireNumericElem("VectorSum", T, loc_id, source_map);
|
|
3567
|
+
return (v) => {
|
|
3568
|
+
if (elem === "Float") {
|
|
3569
|
+
let acc = 0;
|
|
3570
|
+
for (let i = 0; i < v.length; i++)
|
|
3571
|
+
acc += v[i];
|
|
3572
|
+
return acc;
|
|
3573
|
+
}
|
|
3574
|
+
let acc = 0n;
|
|
3575
|
+
for (let i = 0; i < v.length; i++)
|
|
3576
|
+
acc = wrapI64(acc + v[i]);
|
|
3577
|
+
return acc;
|
|
3578
|
+
};
|
|
3579
|
+
},
|
|
3580
|
+
VectorAddScaled: (loc_id, source_map, _platformDef, T) => {
|
|
3581
|
+
const elem = requireNumericElem("VectorAddScaled", T, loc_id, source_map);
|
|
3582
|
+
return (a, b, alpha) => {
|
|
3583
|
+
requireSameLength(a, b, loc_id, source_map);
|
|
3584
|
+
if (elem === "Float") {
|
|
3585
|
+
const result = new Float64Array(a.length);
|
|
3586
|
+
for (let i = 0; i < a.length; i++)
|
|
3587
|
+
result[i] = a[i] + alpha * b[i];
|
|
3588
|
+
return result;
|
|
3589
|
+
}
|
|
3590
|
+
const result = new BigInt64Array(a.length);
|
|
3591
|
+
for (let i = 0; i < a.length; i++)
|
|
3592
|
+
result[i] = wrapI64(a[i] + wrapI64(alpha * b[i]));
|
|
3593
|
+
return result;
|
|
3594
|
+
};
|
|
3595
|
+
},
|
|
3596
|
+
VectorMul: (loc_id, source_map, _platformDef, T) => {
|
|
3597
|
+
const elem = requireNumericElem("VectorMul", T, loc_id, source_map);
|
|
3598
|
+
return (a, b) => {
|
|
3599
|
+
requireSameLength(a, b, loc_id, source_map);
|
|
3600
|
+
if (elem === "Float") {
|
|
3601
|
+
const result = new Float64Array(a.length);
|
|
3602
|
+
for (let i = 0; i < a.length; i++)
|
|
3603
|
+
result[i] = a[i] * b[i];
|
|
3604
|
+
return result;
|
|
3605
|
+
}
|
|
3606
|
+
const result = new BigInt64Array(a.length);
|
|
3607
|
+
for (let i = 0; i < a.length; i++)
|
|
3608
|
+
result[i] = wrapI64(a[i] * b[i]);
|
|
3609
|
+
return result;
|
|
3610
|
+
};
|
|
3611
|
+
},
|
|
3612
|
+
VectorAddScalar: (loc_id, source_map, _platformDef, T) => {
|
|
3613
|
+
const elem = requireNumericElem("VectorAddScalar", T, loc_id, source_map);
|
|
3614
|
+
return (v, c) => {
|
|
3615
|
+
if (elem === "Float") {
|
|
3616
|
+
const result = new Float64Array(v.length);
|
|
3617
|
+
for (let i = 0; i < v.length; i++)
|
|
3618
|
+
result[i] = v[i] + c;
|
|
3619
|
+
return result;
|
|
3620
|
+
}
|
|
3621
|
+
const result = new BigInt64Array(v.length);
|
|
3622
|
+
for (let i = 0; i < v.length; i++)
|
|
3623
|
+
result[i] = wrapI64(v[i] + c);
|
|
3624
|
+
return result;
|
|
3625
|
+
};
|
|
3626
|
+
},
|
|
3627
|
+
VectorDot: (loc_id, source_map, _platformDef, T) => {
|
|
3628
|
+
const elem = requireNumericElem("VectorDot", T, loc_id, source_map);
|
|
3629
|
+
return (a, b) => {
|
|
3630
|
+
requireSameLength(a, b, loc_id, source_map);
|
|
3631
|
+
if (elem === "Float") {
|
|
3632
|
+
let acc = 0;
|
|
3633
|
+
for (let i = 0; i < a.length; i++)
|
|
3634
|
+
acc += a[i] * b[i];
|
|
3635
|
+
return acc;
|
|
3636
|
+
}
|
|
3637
|
+
let acc = 0n;
|
|
3638
|
+
for (let i = 0; i < a.length; i++)
|
|
3639
|
+
acc = wrapI64(acc + wrapI64(a[i] * b[i]));
|
|
3640
|
+
return acc;
|
|
3641
|
+
};
|
|
3642
|
+
},
|
|
3643
|
+
VectorMax: (loc_id, source_map, _platformDef, T) => {
|
|
3644
|
+
requireNumericElem("VectorMax", T, loc_id, source_map);
|
|
3645
|
+
const less = lessFor(T);
|
|
3646
|
+
return (v) => {
|
|
3647
|
+
if (v.length === 0) {
|
|
3648
|
+
throw new EastError("Cannot reduce empty Vector", { location: (source_map?.resolve(loc_id) ?? []) });
|
|
3649
|
+
}
|
|
3650
|
+
let best = v[0];
|
|
3651
|
+
for (let i = 1; i < v.length; i++) {
|
|
3652
|
+
if (less(best, v[i]))
|
|
3653
|
+
best = v[i];
|
|
3654
|
+
}
|
|
3655
|
+
return best;
|
|
3656
|
+
};
|
|
3657
|
+
},
|
|
3658
|
+
VectorMin: (loc_id, source_map, _platformDef, T) => {
|
|
3659
|
+
requireNumericElem("VectorMin", T, loc_id, source_map);
|
|
3660
|
+
const less = lessFor(T);
|
|
3661
|
+
return (v) => {
|
|
3662
|
+
if (v.length === 0) {
|
|
3663
|
+
throw new EastError("Cannot reduce empty Vector", { location: (source_map?.resolve(loc_id) ?? []) });
|
|
3664
|
+
}
|
|
3665
|
+
let best = v[0];
|
|
3666
|
+
for (let i = 1; i < v.length; i++) {
|
|
3667
|
+
if (less(v[i], best))
|
|
3668
|
+
best = v[i];
|
|
3669
|
+
}
|
|
3670
|
+
return best;
|
|
3671
|
+
};
|
|
3672
|
+
},
|
|
3673
|
+
VectorArgMax: (loc_id, source_map, _platformDef, T) => {
|
|
3674
|
+
requireNumericElem("VectorArgMax", T, loc_id, source_map);
|
|
3675
|
+
const less = lessFor(T);
|
|
3676
|
+
return (v) => {
|
|
3677
|
+
if (v.length === 0) {
|
|
3678
|
+
throw new EastError("Cannot reduce empty Vector", { location: (source_map?.resolve(loc_id) ?? []) });
|
|
3679
|
+
}
|
|
3680
|
+
let bestIdx = 0;
|
|
3681
|
+
for (let i = 1; i < v.length; i++) {
|
|
3682
|
+
if (less(v[bestIdx], v[i]))
|
|
3683
|
+
bestIdx = i;
|
|
3684
|
+
}
|
|
3685
|
+
return BigInt(bestIdx);
|
|
3686
|
+
};
|
|
3687
|
+
},
|
|
3688
|
+
VectorArgMin: (loc_id, source_map, _platformDef, T) => {
|
|
3689
|
+
requireNumericElem("VectorArgMin", T, loc_id, source_map);
|
|
3690
|
+
const less = lessFor(T);
|
|
3691
|
+
return (v) => {
|
|
3692
|
+
if (v.length === 0) {
|
|
3693
|
+
throw new EastError("Cannot reduce empty Vector", { location: (source_map?.resolve(loc_id) ?? []) });
|
|
3694
|
+
}
|
|
3695
|
+
let bestIdx = 0;
|
|
3696
|
+
for (let i = 1; i < v.length; i++) {
|
|
3697
|
+
if (less(v[i], v[bestIdx]))
|
|
3698
|
+
bestIdx = i;
|
|
3699
|
+
}
|
|
3700
|
+
return BigInt(bestIdx);
|
|
3701
|
+
};
|
|
3702
|
+
},
|
|
3703
|
+
VectorMean: (loc_id, source_map, _platformDef, T) => {
|
|
3704
|
+
requireNumericElem("VectorMean", T, loc_id, source_map);
|
|
3705
|
+
return (v) => {
|
|
3706
|
+
let acc = 0;
|
|
3707
|
+
for (let i = 0; i < v.length; i++)
|
|
3708
|
+
acc += Number(v[i]);
|
|
3709
|
+
return acc / v.length;
|
|
3710
|
+
};
|
|
3711
|
+
},
|
|
3712
|
+
VectorCumSum: (loc_id, source_map, _platformDef, T) => {
|
|
3713
|
+
const elem = requireNumericElem("VectorCumSum", T, loc_id, source_map);
|
|
3714
|
+
return (v) => {
|
|
3715
|
+
if (elem === "Float") {
|
|
3716
|
+
const result = new Float64Array(v.length);
|
|
3717
|
+
let acc = 0;
|
|
3718
|
+
for (let i = 0; i < v.length; i++) {
|
|
3719
|
+
acc += v[i];
|
|
3720
|
+
result[i] = acc;
|
|
3721
|
+
}
|
|
3722
|
+
return result;
|
|
3723
|
+
}
|
|
3724
|
+
const result = new BigInt64Array(v.length);
|
|
3725
|
+
let acc = 0n;
|
|
3726
|
+
for (let i = 0; i < v.length; i++) {
|
|
3727
|
+
acc = wrapI64(acc + v[i]);
|
|
3728
|
+
result[i] = acc;
|
|
3729
|
+
}
|
|
3730
|
+
return result;
|
|
3731
|
+
};
|
|
3732
|
+
},
|
|
3733
|
+
VectorAbs: (loc_id, source_map, _platformDef, T) => {
|
|
3734
|
+
const elem = requireNumericElem("VectorAbs", T, loc_id, source_map);
|
|
3735
|
+
return (v) => {
|
|
3736
|
+
if (elem === "Float") {
|
|
3737
|
+
const result = new Float64Array(v.length);
|
|
3738
|
+
for (let i = 0; i < v.length; i++) {
|
|
3739
|
+
const x = v[i];
|
|
3740
|
+
result[i] = x < 0 ? -x : x;
|
|
3741
|
+
}
|
|
3742
|
+
return result;
|
|
3743
|
+
}
|
|
3744
|
+
const result = new BigInt64Array(v.length);
|
|
3745
|
+
for (let i = 0; i < v.length; i++) {
|
|
3746
|
+
const x = v[i];
|
|
3747
|
+
result[i] = wrapI64(x < 0n ? -x : x);
|
|
3748
|
+
}
|
|
3749
|
+
return result;
|
|
3750
|
+
};
|
|
3751
|
+
},
|
|
3752
|
+
VectorClamp: (loc_id, source_map, _platformDef, T) => {
|
|
3753
|
+
const elem = requireNumericElem("VectorClamp", T, loc_id, source_map);
|
|
3754
|
+
const less = lessFor(T);
|
|
3755
|
+
return (v, lo, hi) => {
|
|
3756
|
+
const result = elem === "Float" ? new Float64Array(v.length) : new BigInt64Array(v.length);
|
|
3757
|
+
for (let i = 0; i < v.length; i++) {
|
|
3758
|
+
const x = v[i];
|
|
3759
|
+
result[i] = less(x, lo) ? lo : less(hi, x) ? hi : x;
|
|
3760
|
+
}
|
|
3761
|
+
return result;
|
|
3762
|
+
};
|
|
3763
|
+
},
|
|
3764
|
+
// Vector gather/scatter and sorted search
|
|
3765
|
+
VectorGather: (loc_id, source_map, _platformDef, T) => (v, idx) => {
|
|
3766
|
+
const result = allocateTypedArray(T, idx.length);
|
|
3767
|
+
for (let j = 0; j < idx.length; j++) {
|
|
3768
|
+
const i = Number(idx[j]);
|
|
3769
|
+
if (i < 0 || i >= v.length) {
|
|
3770
|
+
throw new EastError(`Vector index ${idx[j]} out of bounds (length ${v.length})`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
3771
|
+
}
|
|
3772
|
+
result[j] = v[i];
|
|
3773
|
+
}
|
|
3774
|
+
return result;
|
|
3775
|
+
},
|
|
3776
|
+
VectorScatterAdd: (loc_id, source_map, _platformDef, T) => {
|
|
3777
|
+
const elem = requireNumericElem("VectorScatterAdd", T, loc_id, source_map);
|
|
3778
|
+
return (dst, idx, src) => {
|
|
3779
|
+
requireSameLength(idx, src, loc_id, source_map);
|
|
3780
|
+
const result = dst.slice();
|
|
3781
|
+
for (let j = 0; j < idx.length; j++) {
|
|
3782
|
+
const i = Number(idx[j]);
|
|
3783
|
+
if (i < 0 || i >= dst.length) {
|
|
3784
|
+
throw new EastError(`Vector index ${idx[j]} out of bounds (length ${dst.length})`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
3785
|
+
}
|
|
3786
|
+
if (elem === "Float") {
|
|
3787
|
+
result[i] = (result[i]) + src[j];
|
|
3788
|
+
}
|
|
3789
|
+
else {
|
|
3790
|
+
result[i] = wrapI64((result[i]) + src[j]);
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
return result;
|
|
3794
|
+
};
|
|
3795
|
+
},
|
|
3796
|
+
VectorSearchSorted: (loc_id, source_map, _platformDef, T) => {
|
|
3797
|
+
const less = lessFor(T);
|
|
3798
|
+
const readElem = T.type === "Boolean"
|
|
3799
|
+
? (v, i) => v[i] !== 0
|
|
3800
|
+
: (v, i) => v[i];
|
|
3801
|
+
return (haystack, needles) => {
|
|
3802
|
+
const result = new BigInt64Array(needles.length);
|
|
3803
|
+
for (let j = 0; j < needles.length; j++) {
|
|
3804
|
+
const needle = readElem(needles, j);
|
|
3805
|
+
let lo = 0;
|
|
3806
|
+
let hi = haystack.length;
|
|
3807
|
+
while (lo < hi) {
|
|
3808
|
+
const mid = (lo + hi) >>> 1;
|
|
3809
|
+
if (less(readElem(haystack, mid), needle)) {
|
|
3810
|
+
lo = mid + 1;
|
|
3811
|
+
}
|
|
3812
|
+
else {
|
|
3813
|
+
hi = mid;
|
|
3814
|
+
}
|
|
3815
|
+
}
|
|
3816
|
+
result[j] = BigInt(lo);
|
|
3817
|
+
}
|
|
3818
|
+
return result;
|
|
3819
|
+
};
|
|
3820
|
+
},
|
|
3821
|
+
// Vector masks and selection (comparisons use East's total order)
|
|
3822
|
+
VectorEq: (loc_id, source_map, _platformDef, T) => {
|
|
3823
|
+
const equal = equalFor(T);
|
|
3824
|
+
const readElem = T.type === "Boolean"
|
|
3825
|
+
? (v, i) => v[i] !== 0
|
|
3826
|
+
: (v, i) => v[i];
|
|
3827
|
+
return (a, b) => {
|
|
3828
|
+
requireSameLength(a, b, loc_id, source_map);
|
|
3829
|
+
const result = new Uint8ClampedArray(a.length);
|
|
3830
|
+
for (let i = 0; i < a.length; i++)
|
|
3831
|
+
result[i] = equal(readElem(a, i), readElem(b, i)) ? 1 : 0;
|
|
3832
|
+
return result;
|
|
3833
|
+
};
|
|
3834
|
+
},
|
|
3835
|
+
VectorLt: (loc_id, source_map, _platformDef, T) => {
|
|
3836
|
+
const less = lessFor(T);
|
|
3837
|
+
const readElem = T.type === "Boolean"
|
|
3838
|
+
? (v, i) => v[i] !== 0
|
|
3839
|
+
: (v, i) => v[i];
|
|
3840
|
+
return (a, b) => {
|
|
3841
|
+
requireSameLength(a, b, loc_id, source_map);
|
|
3842
|
+
const result = new Uint8ClampedArray(a.length);
|
|
3843
|
+
for (let i = 0; i < a.length; i++)
|
|
3844
|
+
result[i] = less(readElem(a, i), readElem(b, i)) ? 1 : 0;
|
|
3845
|
+
return result;
|
|
3846
|
+
};
|
|
3847
|
+
},
|
|
3848
|
+
VectorGt: (loc_id, source_map, _platformDef, T) => {
|
|
3849
|
+
const greater = greaterFor(T);
|
|
3850
|
+
const readElem = T.type === "Boolean"
|
|
3851
|
+
? (v, i) => v[i] !== 0
|
|
3852
|
+
: (v, i) => v[i];
|
|
3853
|
+
return (a, b) => {
|
|
3854
|
+
requireSameLength(a, b, loc_id, source_map);
|
|
3855
|
+
const result = new Uint8ClampedArray(a.length);
|
|
3856
|
+
for (let i = 0; i < a.length; i++)
|
|
3857
|
+
result[i] = greater(readElem(a, i), readElem(b, i)) ? 1 : 0;
|
|
3858
|
+
return result;
|
|
3859
|
+
};
|
|
3860
|
+
},
|
|
3861
|
+
VectorSelect: (loc_id, source_map, _platformDef, T) => (mask, a, b) => {
|
|
3862
|
+
requireSameLength(mask, a, loc_id, source_map);
|
|
3863
|
+
requireSameLength(a, b, loc_id, source_map);
|
|
3864
|
+
const result = allocateTypedArray(T, mask.length);
|
|
3865
|
+
for (let i = 0; i < mask.length; i++)
|
|
3866
|
+
result[i] = (mask[i] !== 0 ? a[i] : b[i]);
|
|
3867
|
+
return result;
|
|
3868
|
+
},
|
|
3869
|
+
VectorCompress: (loc_id, source_map, _platformDef, T) => (mask, v) => {
|
|
3870
|
+
requireSameLength(mask, v, loc_id, source_map);
|
|
3871
|
+
let count = 0;
|
|
3872
|
+
for (let i = 0; i < mask.length; i++) {
|
|
3873
|
+
if (mask[i] !== 0)
|
|
3874
|
+
count++;
|
|
3875
|
+
}
|
|
3876
|
+
const result = allocateTypedArray(T, count);
|
|
3877
|
+
let j = 0;
|
|
3878
|
+
for (let i = 0; i < mask.length; i++) {
|
|
3879
|
+
if (mask[i] !== 0)
|
|
3880
|
+
result[j++] = v[i];
|
|
3881
|
+
}
|
|
3882
|
+
return result;
|
|
3883
|
+
},
|
|
3884
|
+
VectorCountTrue: (_loc_id, _source_map, _platformDef) => (mask) => {
|
|
3885
|
+
let count = 0n;
|
|
3886
|
+
for (let i = 0; i < mask.length; i++) {
|
|
3887
|
+
if (mask[i] !== 0)
|
|
3888
|
+
count += 1n;
|
|
3889
|
+
}
|
|
3890
|
+
return count;
|
|
3891
|
+
},
|
|
3892
|
+
// Sparse accumulators: parallel (ix, v) with strictly ascending ix.
|
|
3893
|
+
// Entries absent from a side are structurally absent, not explicit zeros:
|
|
3894
|
+
// an A-only entry passes through unscaled, a B-only entry contributes
|
|
3895
|
+
// alpha*vB even when alpha is NaN or infinite.
|
|
3896
|
+
SparseAxpy: (loc_id, source_map, _platformDef, T) => {
|
|
3897
|
+
const elem = requireNumericElem("SparseAxpy", T, loc_id, source_map);
|
|
3898
|
+
return (ixA, vA, ixB, vB, alpha) => {
|
|
3899
|
+
requireSparse(ixA, vA, loc_id, source_map);
|
|
3900
|
+
requireSparse(ixB, vB, loc_id, source_map);
|
|
3901
|
+
let count = 0;
|
|
3902
|
+
let i = 0;
|
|
3903
|
+
let j = 0;
|
|
3904
|
+
while (i < ixA.length && j < ixB.length) {
|
|
3905
|
+
const a = ixA[i];
|
|
3906
|
+
const b = ixB[j];
|
|
3907
|
+
if (a < b)
|
|
3908
|
+
i++;
|
|
3909
|
+
else if (b < a)
|
|
3910
|
+
j++;
|
|
3911
|
+
else {
|
|
3912
|
+
i++;
|
|
3913
|
+
j++;
|
|
3914
|
+
}
|
|
3915
|
+
count++;
|
|
3916
|
+
}
|
|
3917
|
+
count += (ixA.length - i) + (ixB.length - j);
|
|
3918
|
+
const outIx = new BigInt64Array(count);
|
|
3919
|
+
const outV = elem === "Float" ? new Float64Array(count) : new BigInt64Array(count);
|
|
3920
|
+
i = 0;
|
|
3921
|
+
j = 0;
|
|
3922
|
+
let k = 0;
|
|
3923
|
+
while (i < ixA.length && j < ixB.length) {
|
|
3924
|
+
const a = ixA[i];
|
|
3925
|
+
const b = ixB[j];
|
|
3926
|
+
if (a < b) {
|
|
3927
|
+
outIx[k] = a;
|
|
3928
|
+
outV[k] = vA[i];
|
|
3929
|
+
i++;
|
|
3930
|
+
}
|
|
3931
|
+
else if (b < a) {
|
|
3932
|
+
outIx[k] = b;
|
|
3933
|
+
outV[k] = elem === "Float" ? alpha * vB[j] : wrapI64(alpha * vB[j]);
|
|
3934
|
+
j++;
|
|
3935
|
+
}
|
|
3936
|
+
else {
|
|
3937
|
+
outIx[k] = a;
|
|
3938
|
+
outV[k] = elem === "Float"
|
|
3939
|
+
? vA[i] + alpha * vB[j]
|
|
3940
|
+
: wrapI64(vA[i] + wrapI64(alpha * vB[j]));
|
|
3941
|
+
i++;
|
|
3942
|
+
j++;
|
|
3943
|
+
}
|
|
3944
|
+
k++;
|
|
3945
|
+
}
|
|
3946
|
+
for (; i < ixA.length; i++, k++) {
|
|
3947
|
+
outIx[k] = ixA[i];
|
|
3948
|
+
outV[k] = vA[i];
|
|
3949
|
+
}
|
|
3950
|
+
for (; j < ixB.length; j++, k++) {
|
|
3951
|
+
outIx[k] = ixB[j];
|
|
3952
|
+
outV[k] = elem === "Float" ? alpha * vB[j] : wrapI64(alpha * vB[j]);
|
|
3953
|
+
}
|
|
3954
|
+
return { ix: outIx, v: outV };
|
|
3955
|
+
};
|
|
3956
|
+
},
|
|
3957
|
+
SparseFromPairs: (loc_id, source_map, _platformDef, T) => {
|
|
3958
|
+
const elem = requireNumericElem("SparseFromPairs", T, loc_id, source_map);
|
|
3959
|
+
return (ix, v) => {
|
|
3960
|
+
if (ix.length !== v.length) {
|
|
3961
|
+
throw new EastError(`Sparse index and value lengths differ (${ix.length} vs ${v.length})`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
3962
|
+
}
|
|
3963
|
+
// Stable: order by (index, original position) so equal indices
|
|
3964
|
+
// accumulate in input order and the float result is deterministic.
|
|
3965
|
+
const order = new Array(ix.length);
|
|
3966
|
+
for (let i = 0; i < ix.length; i++)
|
|
3967
|
+
order[i] = i;
|
|
3968
|
+
order.sort((p, q) => {
|
|
3969
|
+
const a = ix[p];
|
|
3970
|
+
const b = ix[q];
|
|
3971
|
+
if (a < b)
|
|
3972
|
+
return -1;
|
|
3973
|
+
if (a > b)
|
|
3974
|
+
return 1;
|
|
3975
|
+
return p - q;
|
|
3976
|
+
});
|
|
3977
|
+
let count = 0;
|
|
3978
|
+
for (let i = 0; i < order.length; i++) {
|
|
3979
|
+
if (i === 0 || ix[order[i]] !== ix[order[i - 1]])
|
|
3980
|
+
count++;
|
|
3981
|
+
}
|
|
3982
|
+
const outIx = new BigInt64Array(count);
|
|
3983
|
+
const outV = elem === "Float" ? new Float64Array(count) : new BigInt64Array(count);
|
|
3984
|
+
let k = -1;
|
|
3985
|
+
for (let i = 0; i < order.length; i++) {
|
|
3986
|
+
const p = order[i];
|
|
3987
|
+
if (i === 0 || ix[p] !== outIx[k]) {
|
|
3988
|
+
k++;
|
|
3989
|
+
outIx[k] = ix[p];
|
|
3990
|
+
outV[k] = v[p];
|
|
3991
|
+
}
|
|
3992
|
+
else {
|
|
3993
|
+
outV[k] = elem === "Float"
|
|
3994
|
+
? (outV[k]) + v[p]
|
|
3995
|
+
: wrapI64((outV[k]) + v[p]);
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
return { ix: outIx, v: outV };
|
|
3999
|
+
};
|
|
4000
|
+
},
|
|
4001
|
+
SparseFilterGt: (loc_id, source_map, _platformDef, T) => {
|
|
4002
|
+
const elem = requireNumericElem("SparseFilterGt", T, loc_id, source_map);
|
|
4003
|
+
const greater = greaterFor(T);
|
|
4004
|
+
return (ix, v, threshold) => {
|
|
4005
|
+
requireSparse(ix, v, loc_id, source_map);
|
|
4006
|
+
let count = 0;
|
|
4007
|
+
for (let i = 0; i < v.length; i++) {
|
|
4008
|
+
if (greater(v[i], threshold))
|
|
4009
|
+
count++;
|
|
4010
|
+
}
|
|
4011
|
+
const outIx = new BigInt64Array(count);
|
|
4012
|
+
const outV = elem === "Float" ? new Float64Array(count) : new BigInt64Array(count);
|
|
4013
|
+
let k = 0;
|
|
4014
|
+
for (let i = 0; i < v.length; i++) {
|
|
4015
|
+
if (greater(v[i], threshold)) {
|
|
4016
|
+
outIx[k] = ix[i];
|
|
4017
|
+
outV[k] = v[i];
|
|
4018
|
+
k++;
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
return { ix: outIx, v: outV };
|
|
4022
|
+
};
|
|
4023
|
+
},
|
|
3513
4024
|
// Matrix builtins
|
|
3514
4025
|
MatrixRows: (_loc_id, _source_map, _platformDef, _T) => (m) => BigInt(m.rows),
|
|
3515
4026
|
MatrixCols: (_loc_id, _source_map, _platformDef, _T) => (m) => BigInt(m.cols),
|
|
@@ -3677,6 +4188,137 @@ const builtin_evaluators = {
|
|
|
3677
4188
|
data.set(arr[r], r * cols);
|
|
3678
4189
|
return matrix(data, arr.length, cols);
|
|
3679
4190
|
},
|
|
4191
|
+
// Matrix elementwise arithmetic + reductions. Sums accumulate in ascending
|
|
4192
|
+
// index order (row-major for whole-matrix walks, ascending row for column
|
|
4193
|
+
// sums, ascending column within each row for row sums and vec-mul) — the
|
|
4194
|
+
// same left-to-right contract as the Vector reductions.
|
|
4195
|
+
MatrixScale: (loc_id, source_map, _platformDef, T) => {
|
|
4196
|
+
const elem = requireNumericElem("MatrixScale", T, loc_id, source_map);
|
|
4197
|
+
return (m, alpha) => {
|
|
4198
|
+
const src = m.data;
|
|
4199
|
+
if (elem === "Float") {
|
|
4200
|
+
const data = new Float64Array(src.length);
|
|
4201
|
+
for (let i = 0; i < src.length; i++)
|
|
4202
|
+
data[i] = src[i] * alpha;
|
|
4203
|
+
return matrix(data, m.rows, m.cols);
|
|
4204
|
+
}
|
|
4205
|
+
const data = new BigInt64Array(src.length);
|
|
4206
|
+
for (let i = 0; i < src.length; i++)
|
|
4207
|
+
data[i] = wrapI64(src[i] * alpha);
|
|
4208
|
+
return matrix(data, m.rows, m.cols);
|
|
4209
|
+
};
|
|
4210
|
+
},
|
|
4211
|
+
MatrixAddScaled: (loc_id, source_map, _platformDef, T) => {
|
|
4212
|
+
const elem = requireNumericElem("MatrixAddScaled", T, loc_id, source_map);
|
|
4213
|
+
return (a, b, alpha) => {
|
|
4214
|
+
requireSameDims(a, b, loc_id, source_map);
|
|
4215
|
+
const ad = a.data;
|
|
4216
|
+
const bd = b.data;
|
|
4217
|
+
if (elem === "Float") {
|
|
4218
|
+
const data = new Float64Array(ad.length);
|
|
4219
|
+
for (let i = 0; i < ad.length; i++)
|
|
4220
|
+
data[i] = ad[i] + alpha * bd[i];
|
|
4221
|
+
return matrix(data, a.rows, a.cols);
|
|
4222
|
+
}
|
|
4223
|
+
const data = new BigInt64Array(ad.length);
|
|
4224
|
+
for (let i = 0; i < ad.length; i++)
|
|
4225
|
+
data[i] = wrapI64(ad[i] + wrapI64(alpha * bd[i]));
|
|
4226
|
+
return matrix(data, a.rows, a.cols);
|
|
4227
|
+
};
|
|
4228
|
+
},
|
|
4229
|
+
MatrixMulElementwise: (loc_id, source_map, _platformDef, T) => {
|
|
4230
|
+
const elem = requireNumericElem("MatrixMulElementwise", T, loc_id, source_map);
|
|
4231
|
+
return (a, b) => {
|
|
4232
|
+
requireSameDims(a, b, loc_id, source_map);
|
|
4233
|
+
const ad = a.data;
|
|
4234
|
+
const bd = b.data;
|
|
4235
|
+
if (elem === "Float") {
|
|
4236
|
+
const data = new Float64Array(ad.length);
|
|
4237
|
+
for (let i = 0; i < ad.length; i++)
|
|
4238
|
+
data[i] = ad[i] * bd[i];
|
|
4239
|
+
return matrix(data, a.rows, a.cols);
|
|
4240
|
+
}
|
|
4241
|
+
const data = new BigInt64Array(ad.length);
|
|
4242
|
+
for (let i = 0; i < ad.length; i++)
|
|
4243
|
+
data[i] = wrapI64(ad[i] * bd[i]);
|
|
4244
|
+
return matrix(data, a.rows, a.cols);
|
|
4245
|
+
};
|
|
4246
|
+
},
|
|
4247
|
+
MatrixRowSums: (loc_id, source_map, _platformDef, T) => {
|
|
4248
|
+
const elem = requireNumericElem("MatrixRowSums", T, loc_id, source_map);
|
|
4249
|
+
return (m) => {
|
|
4250
|
+
const src = m.data;
|
|
4251
|
+
if (elem === "Float") {
|
|
4252
|
+
const result = new Float64Array(m.rows);
|
|
4253
|
+
for (let r = 0; r < m.rows; r++) {
|
|
4254
|
+
let acc = 0;
|
|
4255
|
+
for (let c = 0; c < m.cols; c++)
|
|
4256
|
+
acc += src[r * m.cols + c];
|
|
4257
|
+
result[r] = acc;
|
|
4258
|
+
}
|
|
4259
|
+
return result;
|
|
4260
|
+
}
|
|
4261
|
+
const result = new BigInt64Array(m.rows);
|
|
4262
|
+
for (let r = 0; r < m.rows; r++) {
|
|
4263
|
+
let acc = 0n;
|
|
4264
|
+
for (let c = 0; c < m.cols; c++)
|
|
4265
|
+
acc = wrapI64(acc + src[r * m.cols + c]);
|
|
4266
|
+
result[r] = acc;
|
|
4267
|
+
}
|
|
4268
|
+
return result;
|
|
4269
|
+
};
|
|
4270
|
+
},
|
|
4271
|
+
MatrixColSums: (loc_id, source_map, _platformDef, T) => {
|
|
4272
|
+
const elem = requireNumericElem("MatrixColSums", T, loc_id, source_map);
|
|
4273
|
+
return (m) => {
|
|
4274
|
+
const src = m.data;
|
|
4275
|
+
if (elem === "Float") {
|
|
4276
|
+
const result = new Float64Array(m.cols);
|
|
4277
|
+
for (let c = 0; c < m.cols; c++) {
|
|
4278
|
+
let acc = 0;
|
|
4279
|
+
for (let r = 0; r < m.rows; r++)
|
|
4280
|
+
acc += src[r * m.cols + c];
|
|
4281
|
+
result[c] = acc;
|
|
4282
|
+
}
|
|
4283
|
+
return result;
|
|
4284
|
+
}
|
|
4285
|
+
const result = new BigInt64Array(m.cols);
|
|
4286
|
+
for (let c = 0; c < m.cols; c++) {
|
|
4287
|
+
let acc = 0n;
|
|
4288
|
+
for (let r = 0; r < m.rows; r++)
|
|
4289
|
+
acc = wrapI64(acc + src[r * m.cols + c]);
|
|
4290
|
+
result[c] = acc;
|
|
4291
|
+
}
|
|
4292
|
+
return result;
|
|
4293
|
+
};
|
|
4294
|
+
},
|
|
4295
|
+
MatrixVecMul: (loc_id, source_map, _platformDef, T) => {
|
|
4296
|
+
const elem = requireNumericElem("MatrixVecMul", T, loc_id, source_map);
|
|
4297
|
+
return (m, v) => {
|
|
4298
|
+
if (v.length !== m.cols) {
|
|
4299
|
+
throw new EastError(`MatrixVecMul dimension mismatch (${m.rows}x${m.cols} vs length ${v.length})`, { location: (source_map?.resolve(loc_id) ?? []) });
|
|
4300
|
+
}
|
|
4301
|
+
const src = m.data;
|
|
4302
|
+
if (elem === "Float") {
|
|
4303
|
+
const result = new Float64Array(m.rows);
|
|
4304
|
+
for (let r = 0; r < m.rows; r++) {
|
|
4305
|
+
let acc = 0;
|
|
4306
|
+
for (let c = 0; c < m.cols; c++)
|
|
4307
|
+
acc += src[r * m.cols + c] * v[c];
|
|
4308
|
+
result[r] = acc;
|
|
4309
|
+
}
|
|
4310
|
+
return result;
|
|
4311
|
+
}
|
|
4312
|
+
const result = new BigInt64Array(m.rows);
|
|
4313
|
+
for (let r = 0; r < m.rows; r++) {
|
|
4314
|
+
let acc = 0n;
|
|
4315
|
+
for (let c = 0; c < m.cols; c++)
|
|
4316
|
+
acc = wrapI64(acc + wrapI64(src[r * m.cols + c] * v[c]));
|
|
4317
|
+
result[r] = acc;
|
|
4318
|
+
}
|
|
4319
|
+
return result;
|
|
4320
|
+
};
|
|
4321
|
+
},
|
|
3680
4322
|
};
|
|
3681
4323
|
/** @internal */
|
|
3682
4324
|
export function applyTypeParameters(t, params) {
|