numbl 0.4.18 → 0.4.21
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-browser/browser.js +1 -1
- package/dist-browser/numbl-core/executors/jit/callExecutor.d.ts +7 -1
- package/dist-browser/numbl-core/executors/jit/loopExecutor.d.ts +12 -7
- package/dist-browser/numbl-core/executors/jit/topLevelExecutor.d.ts +3 -0
- package/dist-browser/numbl-core/executors/jit/valueAdapter.d.ts +9 -2
- package/dist-browser/numbl-core/executors/registry.d.ts +8 -0
- package/dist-browser/numbl-core/helpers/sparse-direct.d.ts +107 -0
- package/dist-browser/numbl-core/helpers/warn.d.ts +9 -0
- package/dist-browser/numbl-core/interpreter/builtins/index.d.ts +1 -0
- package/dist-browser/numbl-core/interpreter/builtins/sparse-solvers.d.ts +16 -0
- package/dist-browser/numbl-core/interpreter/interpreter.d.ts +11 -0
- package/dist-browser/numbl-core/jit/builtins/runtime/system/cscalar.d.ts +4 -4
- package/dist-browser/numbl-core/jit/codegen/emitIndex.d.ts +1 -1
- package/dist-browser/numbl-core/jit/compileSpec.d.ts +4 -0
- package/dist-browser/numbl-core/jit/lowering/lower.d.ts +13 -0
- package/dist-browser/numbl-core/jitDeclineDiagnostics.d.ts +6 -0
- package/dist-browser/numbl-core/native/lapack-bridge.d.ts +29 -1
- package/dist-browser/numbl-core/native/ts-lapack-eig-hermitian.d.ts +33 -0
- package/dist-browser/numbl-core/runtime/types.d.ts +12 -0
- package/dist-browser/numbl-core/version.d.ts +1 -1
- package/dist-browser/ts-lapack/src/BLAS/dsymv.d.ts +1 -0
- package/dist-browser/ts-lapack/src/BLAS/dsyr2.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dlae2.d.ts +4 -0
- package/dist-browser/ts-lapack/src/SRC/dlaev2.d.ts +6 -0
- package/dist-browser/ts-lapack/src/SRC/dlanst.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dlansy.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dlasrt.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dorgtr.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dsteqr.d.ts +4 -0
- package/dist-browser/ts-lapack/src/SRC/dsyev.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dsytd2.d.ts +1 -0
- package/dist-cli/cli.js +3824 -280
- package/dist-lib/lib.js +3636 -113
- package/dist-lib/numbl-core/executors/jit/callExecutor.d.ts +7 -1
- package/dist-lib/numbl-core/executors/jit/loopExecutor.d.ts +12 -7
- package/dist-lib/numbl-core/executors/jit/topLevelExecutor.d.ts +3 -0
- package/dist-lib/numbl-core/executors/jit/valueAdapter.d.ts +9 -2
- package/dist-lib/numbl-core/executors/registry.d.ts +8 -0
- package/dist-lib/numbl-core/helpers/sparse-direct.d.ts +107 -0
- package/dist-lib/numbl-core/helpers/warn.d.ts +9 -0
- package/dist-lib/numbl-core/interpreter/builtins/index.d.ts +1 -0
- package/dist-lib/numbl-core/interpreter/builtins/sparse-solvers.d.ts +16 -0
- package/dist-lib/numbl-core/interpreter/interpreter.d.ts +11 -0
- package/dist-lib/numbl-core/jit/builtins/runtime/system/cscalar.d.ts +4 -4
- package/dist-lib/numbl-core/jit/codegen/emitIndex.d.ts +1 -1
- package/dist-lib/numbl-core/jit/compileSpec.d.ts +4 -0
- package/dist-lib/numbl-core/jit/lowering/lower.d.ts +13 -0
- package/dist-lib/numbl-core/jitDeclineDiagnostics.d.ts +6 -0
- package/dist-lib/numbl-core/native/lapack-bridge.d.ts +29 -1
- package/dist-lib/numbl-core/native/ts-lapack-eig-hermitian.d.ts +33 -0
- package/dist-lib/numbl-core/runtime/types.d.ts +12 -0
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/dist-lib/ts-lapack/src/BLAS/dsymv.d.ts +1 -0
- package/dist-lib/ts-lapack/src/BLAS/dsyr2.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dlae2.d.ts +4 -0
- package/dist-lib/ts-lapack/src/SRC/dlaev2.d.ts +6 -0
- package/dist-lib/ts-lapack/src/SRC/dlanst.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dlansy.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dlasrt.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dorgtr.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dsteqr.d.ts +4 -0
- package/dist-lib/ts-lapack/src/SRC/dsyev.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dsytd2.d.ts +1 -0
- package/dist-site-viewer/assets/index-DrtkDG_M.js +4832 -0
- package/dist-site-viewer/assets/numbl-worker-Dz_Z8B9u.js +5327 -0
- package/dist-site-viewer/index.html +1 -1
- package/native/lapack_eig.cpp +156 -0
- package/native/numbl_addon.cpp +7 -1
- package/native/numbl_addon_common.h +14 -0
- package/package.json +1 -1
- package/dist-site-viewer/assets/index-34LVPucU.js +0 -4831
- package/dist-site-viewer/assets/numbl-worker-BCMSGYEy.js +0 -5339
package/dist-cli/cli.js
CHANGED
|
@@ -940,6 +940,9 @@ var RuntimeSparseMatrix = class extends Refcounted {
|
|
|
940
940
|
jc;
|
|
941
941
|
pr;
|
|
942
942
|
pi;
|
|
943
|
+
/** Lazily computed by triangularInfo(); valid because sparse matrices are
|
|
944
|
+
* never mutated in place (indexed assignment builds a new matrix). */
|
|
945
|
+
_triInfo = void 0;
|
|
943
946
|
constructor(m, n, ir, jc, pr, pi2) {
|
|
944
947
|
super();
|
|
945
948
|
this.m = m;
|
|
@@ -975,7 +978,7 @@ var RuntimeDictionary = class extends Refcounted {
|
|
|
975
978
|
};
|
|
976
979
|
|
|
977
980
|
// src/numbl-core/native/lapack-bridge.ts
|
|
978
|
-
var NATIVE_ADDON_EXPECTED_VERSION =
|
|
981
|
+
var NATIVE_ADDON_EXPECTED_VERSION = 9;
|
|
979
982
|
var _bridge = null;
|
|
980
983
|
function setLapackBridge(bridge) {
|
|
981
984
|
_bridge = bridge;
|
|
@@ -3844,6 +3847,21 @@ function mMulSparse(a, b) {
|
|
|
3844
3847
|
const m = a.m;
|
|
3845
3848
|
const hasImag = isComplexSparse(a) || b.imag !== void 0;
|
|
3846
3849
|
const result = allocFloat64Array(m * bCols);
|
|
3850
|
+
if (!hasImag) {
|
|
3851
|
+
const ir = a.ir, jc = a.jc, pr = a.pr, bd = b.data;
|
|
3852
|
+
for (let col = 0; col < bCols; col++) {
|
|
3853
|
+
const boff = col * bRows;
|
|
3854
|
+
const roff = col * m;
|
|
3855
|
+
for (let k = 0; k < a.n; k++) {
|
|
3856
|
+
const bk = bd[boff + k];
|
|
3857
|
+
if (bk === 0) continue;
|
|
3858
|
+
const end = jc[k + 1];
|
|
3859
|
+
for (let ka = jc[k]; ka < end; ka++)
|
|
3860
|
+
result[roff + ir[ka]] += pr[ka] * bk;
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
return RTV.tensor(result, [m, bCols]);
|
|
3864
|
+
}
|
|
3847
3865
|
const resultImag = hasImag ? allocFloat64Array(m * bCols) : void 0;
|
|
3848
3866
|
for (let col = 0; col < bCols; col++) {
|
|
3849
3867
|
for (let k = 0; k < a.n; k++) {
|
|
@@ -4087,6 +4105,8 @@ var PIVOT_T = 1;
|
|
|
4087
4105
|
var PIVOT_B = 2;
|
|
4088
4106
|
var DIRECT_F = 0;
|
|
4089
4107
|
var DIRECT_B = 1;
|
|
4108
|
+
var SORT_INC = 0;
|
|
4109
|
+
var SORT_DEC = 1;
|
|
4090
4110
|
var VECT_Q = 0;
|
|
4091
4111
|
var VECT_P = 1;
|
|
4092
4112
|
|
|
@@ -20693,6 +20713,1357 @@ function eigComplexTs(dataRe, dataIm, n, computeVL, computeVR) {
|
|
|
20693
20713
|
return result;
|
|
20694
20714
|
}
|
|
20695
20715
|
|
|
20716
|
+
// src/ts-lapack/src/SRC/dlanst.ts
|
|
20717
|
+
var NORM_MAX5 = 0;
|
|
20718
|
+
var NORM_ONE2 = 1;
|
|
20719
|
+
var NORM_INF2 = 2;
|
|
20720
|
+
var NORM_FRO2 = 3;
|
|
20721
|
+
function dlanst(norm2, n, d, dOff, e, eOff) {
|
|
20722
|
+
let anorm = 0;
|
|
20723
|
+
if (n <= 0) {
|
|
20724
|
+
anorm = 0;
|
|
20725
|
+
} else if (norm2 === NORM_MAX5) {
|
|
20726
|
+
anorm = Math.abs(d[dOff + (n - 1)]);
|
|
20727
|
+
for (let i = 1; i <= n - 1; i++) {
|
|
20728
|
+
let sum2 = Math.abs(d[dOff + (i - 1)]);
|
|
20729
|
+
if (anorm < sum2 || Number.isNaN(sum2)) anorm = sum2;
|
|
20730
|
+
sum2 = Math.abs(e[eOff + (i - 1)]);
|
|
20731
|
+
if (anorm < sum2 || Number.isNaN(sum2)) anorm = sum2;
|
|
20732
|
+
}
|
|
20733
|
+
} else if (norm2 === NORM_ONE2 || norm2 === NORM_INF2) {
|
|
20734
|
+
if (n === 1) {
|
|
20735
|
+
anorm = Math.abs(d[dOff]);
|
|
20736
|
+
} else {
|
|
20737
|
+
anorm = Math.abs(d[dOff]) + Math.abs(e[eOff]);
|
|
20738
|
+
let sum2 = Math.abs(e[eOff + (n - 2)]) + Math.abs(d[dOff + (n - 1)]);
|
|
20739
|
+
if (anorm < sum2 || Number.isNaN(sum2)) anorm = sum2;
|
|
20740
|
+
for (let i = 2; i <= n - 1; i++) {
|
|
20741
|
+
sum2 = Math.abs(d[dOff + (i - 1)]) + Math.abs(e[eOff + (i - 1)]) + Math.abs(e[eOff + (i - 2)]);
|
|
20742
|
+
if (anorm < sum2 || Number.isNaN(sum2)) anorm = sum2;
|
|
20743
|
+
}
|
|
20744
|
+
}
|
|
20745
|
+
} else if (norm2 === NORM_FRO2) {
|
|
20746
|
+
const scale = { val: 0 };
|
|
20747
|
+
const sum2 = { val: 1 };
|
|
20748
|
+
if (n > 1) {
|
|
20749
|
+
dlassq(n - 1, e, eOff, 1, scale, sum2);
|
|
20750
|
+
sum2.val = 2 * sum2.val;
|
|
20751
|
+
}
|
|
20752
|
+
dlassq(n, d, dOff, 1, scale, sum2);
|
|
20753
|
+
anorm = scale.val * Math.sqrt(sum2.val);
|
|
20754
|
+
}
|
|
20755
|
+
return anorm;
|
|
20756
|
+
}
|
|
20757
|
+
|
|
20758
|
+
// src/ts-lapack/src/SRC/dlae2.ts
|
|
20759
|
+
function dlae2(a, b, c) {
|
|
20760
|
+
const ONE10 = 1;
|
|
20761
|
+
const TWO = 2;
|
|
20762
|
+
const HALF = 0.5;
|
|
20763
|
+
const sm = a + c;
|
|
20764
|
+
const df = a - c;
|
|
20765
|
+
const adf = Math.abs(df);
|
|
20766
|
+
const tb = b + b;
|
|
20767
|
+
const ab = Math.abs(tb);
|
|
20768
|
+
let acmx, acmn;
|
|
20769
|
+
if (Math.abs(a) > Math.abs(c)) {
|
|
20770
|
+
acmx = a;
|
|
20771
|
+
acmn = c;
|
|
20772
|
+
} else {
|
|
20773
|
+
acmx = c;
|
|
20774
|
+
acmn = a;
|
|
20775
|
+
}
|
|
20776
|
+
let rt;
|
|
20777
|
+
if (adf > ab) {
|
|
20778
|
+
rt = adf * Math.sqrt(ONE10 + (ab / adf) ** 2);
|
|
20779
|
+
} else if (adf < ab) {
|
|
20780
|
+
rt = ab * Math.sqrt(ONE10 + (adf / ab) ** 2);
|
|
20781
|
+
} else {
|
|
20782
|
+
rt = ab * Math.sqrt(TWO);
|
|
20783
|
+
}
|
|
20784
|
+
let rt1, rt2;
|
|
20785
|
+
if (sm < 0) {
|
|
20786
|
+
rt1 = HALF * (sm - rt);
|
|
20787
|
+
rt2 = acmx / rt1 * acmn - b / rt1 * b;
|
|
20788
|
+
} else if (sm > 0) {
|
|
20789
|
+
rt1 = HALF * (sm + rt);
|
|
20790
|
+
rt2 = acmx / rt1 * acmn - b / rt1 * b;
|
|
20791
|
+
} else {
|
|
20792
|
+
rt1 = HALF * rt;
|
|
20793
|
+
rt2 = -HALF * rt;
|
|
20794
|
+
}
|
|
20795
|
+
return { rt1, rt2 };
|
|
20796
|
+
}
|
|
20797
|
+
|
|
20798
|
+
// src/ts-lapack/src/SRC/dlaev2.ts
|
|
20799
|
+
function dlaev2(a, b, c) {
|
|
20800
|
+
const ONE10 = 1;
|
|
20801
|
+
const TWO = 2;
|
|
20802
|
+
const HALF = 0.5;
|
|
20803
|
+
const sm = a + c;
|
|
20804
|
+
const df = a - c;
|
|
20805
|
+
const adf = Math.abs(df);
|
|
20806
|
+
const tb = b + b;
|
|
20807
|
+
const ab = Math.abs(tb);
|
|
20808
|
+
let acmx, acmn;
|
|
20809
|
+
if (Math.abs(a) > Math.abs(c)) {
|
|
20810
|
+
acmx = a;
|
|
20811
|
+
acmn = c;
|
|
20812
|
+
} else {
|
|
20813
|
+
acmx = c;
|
|
20814
|
+
acmn = a;
|
|
20815
|
+
}
|
|
20816
|
+
let rt;
|
|
20817
|
+
if (adf > ab) {
|
|
20818
|
+
rt = adf * Math.sqrt(ONE10 + (ab / adf) ** 2);
|
|
20819
|
+
} else if (adf < ab) {
|
|
20820
|
+
rt = ab * Math.sqrt(ONE10 + (adf / ab) ** 2);
|
|
20821
|
+
} else {
|
|
20822
|
+
rt = ab * Math.sqrt(TWO);
|
|
20823
|
+
}
|
|
20824
|
+
let rt1, rt2, sgn1;
|
|
20825
|
+
if (sm < 0) {
|
|
20826
|
+
rt1 = HALF * (sm - rt);
|
|
20827
|
+
sgn1 = -1;
|
|
20828
|
+
rt2 = acmx / rt1 * acmn - b / rt1 * b;
|
|
20829
|
+
} else if (sm > 0) {
|
|
20830
|
+
rt1 = HALF * (sm + rt);
|
|
20831
|
+
sgn1 = 1;
|
|
20832
|
+
rt2 = acmx / rt1 * acmn - b / rt1 * b;
|
|
20833
|
+
} else {
|
|
20834
|
+
rt1 = HALF * rt;
|
|
20835
|
+
rt2 = -HALF * rt;
|
|
20836
|
+
sgn1 = 1;
|
|
20837
|
+
}
|
|
20838
|
+
let cs, sgn2;
|
|
20839
|
+
if (df >= 0) {
|
|
20840
|
+
cs = df + rt;
|
|
20841
|
+
sgn2 = 1;
|
|
20842
|
+
} else {
|
|
20843
|
+
cs = df - rt;
|
|
20844
|
+
sgn2 = -1;
|
|
20845
|
+
}
|
|
20846
|
+
let cs1, sn1;
|
|
20847
|
+
const acs = Math.abs(cs);
|
|
20848
|
+
if (acs > ab) {
|
|
20849
|
+
const ct = -tb / cs;
|
|
20850
|
+
sn1 = ONE10 / Math.sqrt(ONE10 + ct * ct);
|
|
20851
|
+
cs1 = ct * sn1;
|
|
20852
|
+
} else {
|
|
20853
|
+
if (ab === 0) {
|
|
20854
|
+
cs1 = ONE10;
|
|
20855
|
+
sn1 = 0;
|
|
20856
|
+
} else {
|
|
20857
|
+
const tn = -cs / tb;
|
|
20858
|
+
cs1 = ONE10 / Math.sqrt(ONE10 + tn * tn);
|
|
20859
|
+
sn1 = tn * cs1;
|
|
20860
|
+
}
|
|
20861
|
+
}
|
|
20862
|
+
if (sgn1 === sgn2) {
|
|
20863
|
+
const tn = cs1;
|
|
20864
|
+
cs1 = -sn1;
|
|
20865
|
+
sn1 = tn;
|
|
20866
|
+
}
|
|
20867
|
+
return { rt1, rt2, cs1, sn1 };
|
|
20868
|
+
}
|
|
20869
|
+
|
|
20870
|
+
// src/ts-lapack/src/SRC/dlasrt.ts
|
|
20871
|
+
function dlasrt(id, n, d, dOff) {
|
|
20872
|
+
const SELECT = 20;
|
|
20873
|
+
let info = 0;
|
|
20874
|
+
let dir = -1;
|
|
20875
|
+
if (id === SORT_DEC) {
|
|
20876
|
+
dir = 0;
|
|
20877
|
+
} else if (id === SORT_INC) {
|
|
20878
|
+
dir = 1;
|
|
20879
|
+
}
|
|
20880
|
+
if (dir === -1) {
|
|
20881
|
+
info = -1;
|
|
20882
|
+
} else if (n < 0) {
|
|
20883
|
+
info = -2;
|
|
20884
|
+
}
|
|
20885
|
+
if (info !== 0) {
|
|
20886
|
+
return info;
|
|
20887
|
+
}
|
|
20888
|
+
if (n <= 1) {
|
|
20889
|
+
return 0;
|
|
20890
|
+
}
|
|
20891
|
+
const stack1 = new Int32Array(33);
|
|
20892
|
+
const stack2 = new Int32Array(33);
|
|
20893
|
+
let stkpnt = 1;
|
|
20894
|
+
stack1[1] = 1;
|
|
20895
|
+
stack2[1] = n;
|
|
20896
|
+
while (stkpnt > 0) {
|
|
20897
|
+
const start = stack1[stkpnt];
|
|
20898
|
+
const endd = stack2[stkpnt];
|
|
20899
|
+
stkpnt--;
|
|
20900
|
+
if (endd - start <= SELECT && endd - start > 0) {
|
|
20901
|
+
if (dir === 0) {
|
|
20902
|
+
for (let i = start + 1; i <= endd; i++) {
|
|
20903
|
+
for (let j = i; j >= start + 1; j--) {
|
|
20904
|
+
if (d[dOff + (j - 1)] > d[dOff + (j - 2)]) {
|
|
20905
|
+
const dmnmx = d[dOff + (j - 1)];
|
|
20906
|
+
d[dOff + (j - 1)] = d[dOff + (j - 2)];
|
|
20907
|
+
d[dOff + (j - 2)] = dmnmx;
|
|
20908
|
+
} else {
|
|
20909
|
+
break;
|
|
20910
|
+
}
|
|
20911
|
+
}
|
|
20912
|
+
}
|
|
20913
|
+
} else {
|
|
20914
|
+
for (let i = start + 1; i <= endd; i++) {
|
|
20915
|
+
for (let j = i; j >= start + 1; j--) {
|
|
20916
|
+
if (d[dOff + (j - 1)] < d[dOff + (j - 2)]) {
|
|
20917
|
+
const dmnmx = d[dOff + (j - 1)];
|
|
20918
|
+
d[dOff + (j - 1)] = d[dOff + (j - 2)];
|
|
20919
|
+
d[dOff + (j - 2)] = dmnmx;
|
|
20920
|
+
} else {
|
|
20921
|
+
break;
|
|
20922
|
+
}
|
|
20923
|
+
}
|
|
20924
|
+
}
|
|
20925
|
+
}
|
|
20926
|
+
} else if (endd - start > SELECT) {
|
|
20927
|
+
const d1 = d[dOff + (start - 1)];
|
|
20928
|
+
const d2 = d[dOff + (endd - 1)];
|
|
20929
|
+
const ii = Math.trunc((start + endd) / 2);
|
|
20930
|
+
const d3 = d[dOff + (ii - 1)];
|
|
20931
|
+
let dmnmx;
|
|
20932
|
+
if (d1 < d2) {
|
|
20933
|
+
if (d3 < d1) {
|
|
20934
|
+
dmnmx = d1;
|
|
20935
|
+
} else if (d3 < d2) {
|
|
20936
|
+
dmnmx = d3;
|
|
20937
|
+
} else {
|
|
20938
|
+
dmnmx = d2;
|
|
20939
|
+
}
|
|
20940
|
+
} else {
|
|
20941
|
+
if (d3 < d2) {
|
|
20942
|
+
dmnmx = d2;
|
|
20943
|
+
} else if (d3 < d1) {
|
|
20944
|
+
dmnmx = d3;
|
|
20945
|
+
} else {
|
|
20946
|
+
dmnmx = d1;
|
|
20947
|
+
}
|
|
20948
|
+
}
|
|
20949
|
+
let i;
|
|
20950
|
+
let j;
|
|
20951
|
+
if (dir === 0) {
|
|
20952
|
+
i = start - 1;
|
|
20953
|
+
j = endd + 1;
|
|
20954
|
+
while (true) {
|
|
20955
|
+
do {
|
|
20956
|
+
j--;
|
|
20957
|
+
} while (d[dOff + (j - 1)] < dmnmx);
|
|
20958
|
+
do {
|
|
20959
|
+
i++;
|
|
20960
|
+
} while (d[dOff + (i - 1)] > dmnmx);
|
|
20961
|
+
if (i < j) {
|
|
20962
|
+
const tmp = d[dOff + (i - 1)];
|
|
20963
|
+
d[dOff + (i - 1)] = d[dOff + (j - 1)];
|
|
20964
|
+
d[dOff + (j - 1)] = tmp;
|
|
20965
|
+
} else {
|
|
20966
|
+
break;
|
|
20967
|
+
}
|
|
20968
|
+
}
|
|
20969
|
+
if (j - start > endd - j - 1) {
|
|
20970
|
+
stkpnt++;
|
|
20971
|
+
stack1[stkpnt] = start;
|
|
20972
|
+
stack2[stkpnt] = j;
|
|
20973
|
+
stkpnt++;
|
|
20974
|
+
stack1[stkpnt] = j + 1;
|
|
20975
|
+
stack2[stkpnt] = endd;
|
|
20976
|
+
} else {
|
|
20977
|
+
stkpnt++;
|
|
20978
|
+
stack1[stkpnt] = j + 1;
|
|
20979
|
+
stack2[stkpnt] = endd;
|
|
20980
|
+
stkpnt++;
|
|
20981
|
+
stack1[stkpnt] = start;
|
|
20982
|
+
stack2[stkpnt] = j;
|
|
20983
|
+
}
|
|
20984
|
+
} else {
|
|
20985
|
+
i = start - 1;
|
|
20986
|
+
j = endd + 1;
|
|
20987
|
+
while (true) {
|
|
20988
|
+
do {
|
|
20989
|
+
j--;
|
|
20990
|
+
} while (d[dOff + (j - 1)] > dmnmx);
|
|
20991
|
+
do {
|
|
20992
|
+
i++;
|
|
20993
|
+
} while (d[dOff + (i - 1)] < dmnmx);
|
|
20994
|
+
if (i < j) {
|
|
20995
|
+
const tmp = d[dOff + (i - 1)];
|
|
20996
|
+
d[dOff + (i - 1)] = d[dOff + (j - 1)];
|
|
20997
|
+
d[dOff + (j - 1)] = tmp;
|
|
20998
|
+
} else {
|
|
20999
|
+
break;
|
|
21000
|
+
}
|
|
21001
|
+
}
|
|
21002
|
+
if (j - start > endd - j - 1) {
|
|
21003
|
+
stkpnt++;
|
|
21004
|
+
stack1[stkpnt] = start;
|
|
21005
|
+
stack2[stkpnt] = j;
|
|
21006
|
+
stkpnt++;
|
|
21007
|
+
stack1[stkpnt] = j + 1;
|
|
21008
|
+
stack2[stkpnt] = endd;
|
|
21009
|
+
} else {
|
|
21010
|
+
stkpnt++;
|
|
21011
|
+
stack1[stkpnt] = j + 1;
|
|
21012
|
+
stack2[stkpnt] = endd;
|
|
21013
|
+
stkpnt++;
|
|
21014
|
+
stack1[stkpnt] = start;
|
|
21015
|
+
stack2[stkpnt] = j;
|
|
21016
|
+
}
|
|
21017
|
+
}
|
|
21018
|
+
}
|
|
21019
|
+
}
|
|
21020
|
+
return 0;
|
|
21021
|
+
}
|
|
21022
|
+
|
|
21023
|
+
// src/ts-lapack/src/SRC/dsteqr.ts
|
|
21024
|
+
var COMPZ_N = 0;
|
|
21025
|
+
var COMPZ_V = 1;
|
|
21026
|
+
var COMPZ_I = 2;
|
|
21027
|
+
var NORM_MAX6 = 0;
|
|
21028
|
+
var TYPE_G3 = 0;
|
|
21029
|
+
var UPLO_FULL2 = -1;
|
|
21030
|
+
function fsign6(a, b) {
|
|
21031
|
+
return b >= 0 ? Math.abs(a) : -Math.abs(a);
|
|
21032
|
+
}
|
|
21033
|
+
function dsteqr(compz, n, d, dOff, e, eOff, z, zOff, ldz, work, workOff) {
|
|
21034
|
+
const ZERO9 = 0;
|
|
21035
|
+
const ONE10 = 1;
|
|
21036
|
+
const TWO = 2;
|
|
21037
|
+
const THREE = 3;
|
|
21038
|
+
const MAXIT = 30;
|
|
21039
|
+
let info = 0;
|
|
21040
|
+
if (compz !== COMPZ_N && compz !== COMPZ_V && compz !== COMPZ_I) {
|
|
21041
|
+
info = -1;
|
|
21042
|
+
} else if (n < 0) {
|
|
21043
|
+
info = -2;
|
|
21044
|
+
} else if (ldz < 1 || compz > 0 && ldz < Math.max(1, n)) {
|
|
21045
|
+
info = -6;
|
|
21046
|
+
}
|
|
21047
|
+
if (info !== 0) {
|
|
21048
|
+
xerbla("DSTEQR", -info);
|
|
21049
|
+
return info;
|
|
21050
|
+
}
|
|
21051
|
+
if (n === 0) return 0;
|
|
21052
|
+
if (n === 1) {
|
|
21053
|
+
if (compz === COMPZ_I) z[zOff] = ONE10;
|
|
21054
|
+
return 0;
|
|
21055
|
+
}
|
|
21056
|
+
const D = (i) => dOff + (i - 1);
|
|
21057
|
+
const E = (i) => eOff + (i - 1);
|
|
21058
|
+
const Zc = (j) => zOff + (j - 1) * ldz;
|
|
21059
|
+
const W = (i) => workOff + (i - 1);
|
|
21060
|
+
const eps2 = dlamch(MACH_EPS);
|
|
21061
|
+
const eps22 = eps2 * eps2;
|
|
21062
|
+
const safmin = dlamch(MACH_SFMIN);
|
|
21063
|
+
const safmax = ONE10 / safmin;
|
|
21064
|
+
const ssfmax = Math.sqrt(safmax) / THREE;
|
|
21065
|
+
const ssfmin = Math.sqrt(safmin) / eps22;
|
|
21066
|
+
if (compz === COMPZ_I) dlaset(UPLO_FULL2, n, n, ZERO9, ONE10, z, zOff, ldz);
|
|
21067
|
+
const nmaxit = n * MAXIT;
|
|
21068
|
+
let jtot = 0;
|
|
21069
|
+
let l1 = 1;
|
|
21070
|
+
const nm1 = n - 1;
|
|
21071
|
+
let ordered = false;
|
|
21072
|
+
outer: for (; ; ) {
|
|
21073
|
+
if (l1 > n) {
|
|
21074
|
+
ordered = true;
|
|
21075
|
+
break outer;
|
|
21076
|
+
}
|
|
21077
|
+
if (l1 > 1) e[E(l1 - 1)] = ZERO9;
|
|
21078
|
+
let m = n;
|
|
21079
|
+
if (l1 <= nm1) {
|
|
21080
|
+
let split = false;
|
|
21081
|
+
for (m = l1; m <= nm1; m++) {
|
|
21082
|
+
const tst = Math.abs(e[E(m)]);
|
|
21083
|
+
if (tst === ZERO9) {
|
|
21084
|
+
split = true;
|
|
21085
|
+
break;
|
|
21086
|
+
}
|
|
21087
|
+
if (tst <= Math.sqrt(Math.abs(d[D(m)])) * Math.sqrt(Math.abs(d[D(m + 1)])) * eps2) {
|
|
21088
|
+
e[E(m)] = ZERO9;
|
|
21089
|
+
split = true;
|
|
21090
|
+
break;
|
|
21091
|
+
}
|
|
21092
|
+
}
|
|
21093
|
+
if (!split) m = n;
|
|
21094
|
+
}
|
|
21095
|
+
let l = l1;
|
|
21096
|
+
const lsv = l;
|
|
21097
|
+
let lend = m;
|
|
21098
|
+
const lendsv = lend;
|
|
21099
|
+
l1 = m + 1;
|
|
21100
|
+
if (lend === l) continue outer;
|
|
21101
|
+
const anorm = dlanst(NORM_MAX6, lend - l + 1, d, D(l), e, E(l));
|
|
21102
|
+
let iscale = 0;
|
|
21103
|
+
if (anorm === ZERO9) continue outer;
|
|
21104
|
+
if (anorm > ssfmax) {
|
|
21105
|
+
iscale = 1;
|
|
21106
|
+
dlascl(TYPE_G3, 0, 0, anorm, ssfmax, lend - l + 1, 1, d, D(l), n);
|
|
21107
|
+
dlascl(TYPE_G3, 0, 0, anorm, ssfmax, lend - l, 1, e, E(l), n);
|
|
21108
|
+
} else if (anorm < ssfmin) {
|
|
21109
|
+
iscale = 2;
|
|
21110
|
+
dlascl(TYPE_G3, 0, 0, anorm, ssfmin, lend - l + 1, 1, d, D(l), n);
|
|
21111
|
+
dlascl(TYPE_G3, 0, 0, anorm, ssfmin, lend - l, 1, e, E(l), n);
|
|
21112
|
+
}
|
|
21113
|
+
if (Math.abs(d[D(lend)]) < Math.abs(d[D(l)])) {
|
|
21114
|
+
lend = lsv;
|
|
21115
|
+
l = lendsv;
|
|
21116
|
+
}
|
|
21117
|
+
if (lend > l) {
|
|
21118
|
+
ql: for (; ; ) {
|
|
21119
|
+
if (l !== lend) {
|
|
21120
|
+
let found = false;
|
|
21121
|
+
for (m = l; m <= lend - 1; m++) {
|
|
21122
|
+
const tst = Math.abs(e[E(m)]) ** 2;
|
|
21123
|
+
if (tst <= eps22 * Math.abs(d[D(m)]) * Math.abs(d[D(m + 1)]) + safmin) {
|
|
21124
|
+
found = true;
|
|
21125
|
+
break;
|
|
21126
|
+
}
|
|
21127
|
+
}
|
|
21128
|
+
if (!found) m = lend;
|
|
21129
|
+
} else {
|
|
21130
|
+
m = lend;
|
|
21131
|
+
}
|
|
21132
|
+
if (m < lend) e[E(m)] = ZERO9;
|
|
21133
|
+
let p2 = d[D(l)];
|
|
21134
|
+
if (m === l) {
|
|
21135
|
+
d[D(l)] = p2;
|
|
21136
|
+
l = l + 1;
|
|
21137
|
+
if (l <= lend) continue ql;
|
|
21138
|
+
break ql;
|
|
21139
|
+
}
|
|
21140
|
+
if (m === l + 1) {
|
|
21141
|
+
if (compz > 0) {
|
|
21142
|
+
const r2 = dlaev2(d[D(l)], e[E(l)], d[D(l + 1)]);
|
|
21143
|
+
work[W(l)] = r2.cs1;
|
|
21144
|
+
work[W(n - 1 + l)] = r2.sn1;
|
|
21145
|
+
dlasr(
|
|
21146
|
+
RIGHT,
|
|
21147
|
+
PIVOT_V,
|
|
21148
|
+
DIRECT_B,
|
|
21149
|
+
n,
|
|
21150
|
+
2,
|
|
21151
|
+
work,
|
|
21152
|
+
W(l),
|
|
21153
|
+
work,
|
|
21154
|
+
W(n - 1 + l),
|
|
21155
|
+
z,
|
|
21156
|
+
Zc(l),
|
|
21157
|
+
ldz
|
|
21158
|
+
);
|
|
21159
|
+
d[D(l)] = r2.rt1;
|
|
21160
|
+
d[D(l + 1)] = r2.rt2;
|
|
21161
|
+
} else {
|
|
21162
|
+
const r2 = dlae2(d[D(l)], e[E(l)], d[D(l + 1)]);
|
|
21163
|
+
d[D(l)] = r2.rt1;
|
|
21164
|
+
d[D(l + 1)] = r2.rt2;
|
|
21165
|
+
}
|
|
21166
|
+
e[E(l)] = ZERO9;
|
|
21167
|
+
l = l + 2;
|
|
21168
|
+
if (l <= lend) continue ql;
|
|
21169
|
+
break ql;
|
|
21170
|
+
}
|
|
21171
|
+
if (jtot === nmaxit) break ql;
|
|
21172
|
+
jtot = jtot + 1;
|
|
21173
|
+
let g = (d[D(l + 1)] - p2) / (TWO * e[E(l)]);
|
|
21174
|
+
let r = dlapy2(g, ONE10);
|
|
21175
|
+
g = d[D(m)] - p2 + e[E(l)] / (g + fsign6(r, g));
|
|
21176
|
+
let s = ONE10;
|
|
21177
|
+
let c = ONE10;
|
|
21178
|
+
p2 = ZERO9;
|
|
21179
|
+
for (let i = m - 1; i >= l; i--) {
|
|
21180
|
+
const f = s * e[E(i)];
|
|
21181
|
+
const b = c * e[E(i)];
|
|
21182
|
+
const rot = dlartg(g, f);
|
|
21183
|
+
c = rot.cs;
|
|
21184
|
+
s = rot.sn;
|
|
21185
|
+
r = rot.r;
|
|
21186
|
+
if (i !== m - 1) e[E(i + 1)] = r;
|
|
21187
|
+
g = d[D(i + 1)] - p2;
|
|
21188
|
+
r = (d[D(i)] - g) * s + TWO * c * b;
|
|
21189
|
+
p2 = s * r;
|
|
21190
|
+
d[D(i + 1)] = g + p2;
|
|
21191
|
+
g = c * r - b;
|
|
21192
|
+
if (compz > 0) {
|
|
21193
|
+
work[W(i)] = c;
|
|
21194
|
+
work[W(n - 1 + i)] = -s;
|
|
21195
|
+
}
|
|
21196
|
+
}
|
|
21197
|
+
if (compz > 0) {
|
|
21198
|
+
const mm = m - l + 1;
|
|
21199
|
+
dlasr(
|
|
21200
|
+
RIGHT,
|
|
21201
|
+
PIVOT_V,
|
|
21202
|
+
DIRECT_B,
|
|
21203
|
+
n,
|
|
21204
|
+
mm,
|
|
21205
|
+
work,
|
|
21206
|
+
W(l),
|
|
21207
|
+
work,
|
|
21208
|
+
W(n - 1 + l),
|
|
21209
|
+
z,
|
|
21210
|
+
Zc(l),
|
|
21211
|
+
ldz
|
|
21212
|
+
);
|
|
21213
|
+
}
|
|
21214
|
+
d[D(l)] = d[D(l)] - p2;
|
|
21215
|
+
e[E(l)] = g;
|
|
21216
|
+
continue ql;
|
|
21217
|
+
}
|
|
21218
|
+
} else {
|
|
21219
|
+
qr: for (; ; ) {
|
|
21220
|
+
if (l !== lend) {
|
|
21221
|
+
let found = false;
|
|
21222
|
+
for (m = l; m >= lend + 1; m--) {
|
|
21223
|
+
const tst = Math.abs(e[E(m - 1)]) ** 2;
|
|
21224
|
+
if (tst <= eps22 * Math.abs(d[D(m)]) * Math.abs(d[D(m - 1)]) + safmin) {
|
|
21225
|
+
found = true;
|
|
21226
|
+
break;
|
|
21227
|
+
}
|
|
21228
|
+
}
|
|
21229
|
+
if (!found) m = lend;
|
|
21230
|
+
} else {
|
|
21231
|
+
m = lend;
|
|
21232
|
+
}
|
|
21233
|
+
if (m > lend) e[E(m - 1)] = ZERO9;
|
|
21234
|
+
let p2 = d[D(l)];
|
|
21235
|
+
if (m === l) {
|
|
21236
|
+
d[D(l)] = p2;
|
|
21237
|
+
l = l - 1;
|
|
21238
|
+
if (l >= lend) continue qr;
|
|
21239
|
+
break qr;
|
|
21240
|
+
}
|
|
21241
|
+
if (m === l - 1) {
|
|
21242
|
+
if (compz > 0) {
|
|
21243
|
+
const r2 = dlaev2(d[D(l - 1)], e[E(l - 1)], d[D(l)]);
|
|
21244
|
+
work[W(m)] = r2.cs1;
|
|
21245
|
+
work[W(n - 1 + m)] = r2.sn1;
|
|
21246
|
+
dlasr(
|
|
21247
|
+
RIGHT,
|
|
21248
|
+
PIVOT_V,
|
|
21249
|
+
DIRECT_F,
|
|
21250
|
+
n,
|
|
21251
|
+
2,
|
|
21252
|
+
work,
|
|
21253
|
+
W(m),
|
|
21254
|
+
work,
|
|
21255
|
+
W(n - 1 + m),
|
|
21256
|
+
z,
|
|
21257
|
+
Zc(l - 1),
|
|
21258
|
+
ldz
|
|
21259
|
+
);
|
|
21260
|
+
d[D(l - 1)] = r2.rt1;
|
|
21261
|
+
d[D(l)] = r2.rt2;
|
|
21262
|
+
} else {
|
|
21263
|
+
const r2 = dlae2(d[D(l - 1)], e[E(l - 1)], d[D(l)]);
|
|
21264
|
+
d[D(l - 1)] = r2.rt1;
|
|
21265
|
+
d[D(l)] = r2.rt2;
|
|
21266
|
+
}
|
|
21267
|
+
e[E(l - 1)] = ZERO9;
|
|
21268
|
+
l = l - 2;
|
|
21269
|
+
if (l >= lend) continue qr;
|
|
21270
|
+
break qr;
|
|
21271
|
+
}
|
|
21272
|
+
if (jtot === nmaxit) break qr;
|
|
21273
|
+
jtot = jtot + 1;
|
|
21274
|
+
let g = (d[D(l - 1)] - p2) / (TWO * e[E(l - 1)]);
|
|
21275
|
+
let r = dlapy2(g, ONE10);
|
|
21276
|
+
g = d[D(m)] - p2 + e[E(l - 1)] / (g + fsign6(r, g));
|
|
21277
|
+
let s = ONE10;
|
|
21278
|
+
let c = ONE10;
|
|
21279
|
+
p2 = ZERO9;
|
|
21280
|
+
for (let i = m; i <= l - 1; i++) {
|
|
21281
|
+
const f = s * e[E(i)];
|
|
21282
|
+
const b = c * e[E(i)];
|
|
21283
|
+
const rot = dlartg(g, f);
|
|
21284
|
+
c = rot.cs;
|
|
21285
|
+
s = rot.sn;
|
|
21286
|
+
r = rot.r;
|
|
21287
|
+
if (i !== m) e[E(i - 1)] = r;
|
|
21288
|
+
g = d[D(i)] - p2;
|
|
21289
|
+
r = (d[D(i + 1)] - g) * s + TWO * c * b;
|
|
21290
|
+
p2 = s * r;
|
|
21291
|
+
d[D(i)] = g + p2;
|
|
21292
|
+
g = c * r - b;
|
|
21293
|
+
if (compz > 0) {
|
|
21294
|
+
work[W(i)] = c;
|
|
21295
|
+
work[W(n - 1 + i)] = s;
|
|
21296
|
+
}
|
|
21297
|
+
}
|
|
21298
|
+
if (compz > 0) {
|
|
21299
|
+
const mm = l - m + 1;
|
|
21300
|
+
dlasr(
|
|
21301
|
+
RIGHT,
|
|
21302
|
+
PIVOT_V,
|
|
21303
|
+
DIRECT_F,
|
|
21304
|
+
n,
|
|
21305
|
+
mm,
|
|
21306
|
+
work,
|
|
21307
|
+
W(m),
|
|
21308
|
+
work,
|
|
21309
|
+
W(n - 1 + m),
|
|
21310
|
+
z,
|
|
21311
|
+
Zc(m),
|
|
21312
|
+
ldz
|
|
21313
|
+
);
|
|
21314
|
+
}
|
|
21315
|
+
d[D(l)] = d[D(l)] - p2;
|
|
21316
|
+
e[E(l - 1)] = g;
|
|
21317
|
+
continue qr;
|
|
21318
|
+
}
|
|
21319
|
+
}
|
|
21320
|
+
if (iscale === 1) {
|
|
21321
|
+
dlascl(TYPE_G3, 0, 0, ssfmax, anorm, lendsv - lsv + 1, 1, d, D(lsv), n);
|
|
21322
|
+
dlascl(TYPE_G3, 0, 0, ssfmax, anorm, lendsv - lsv, 1, e, E(lsv), n);
|
|
21323
|
+
} else if (iscale === 2) {
|
|
21324
|
+
dlascl(TYPE_G3, 0, 0, ssfmin, anorm, lendsv - lsv + 1, 1, d, D(lsv), n);
|
|
21325
|
+
dlascl(TYPE_G3, 0, 0, ssfmin, anorm, lendsv - lsv, 1, e, E(lsv), n);
|
|
21326
|
+
}
|
|
21327
|
+
if (jtot < nmaxit) continue outer;
|
|
21328
|
+
for (let i = 1; i <= n - 1; i++) {
|
|
21329
|
+
if (e[E(i)] !== ZERO9) info = info + 1;
|
|
21330
|
+
}
|
|
21331
|
+
break outer;
|
|
21332
|
+
}
|
|
21333
|
+
if (!ordered) return info;
|
|
21334
|
+
if (compz === COMPZ_N) {
|
|
21335
|
+
const sortInfo = dlasrt(SORT_INC, n, d, dOff);
|
|
21336
|
+
if (sortInfo !== 0) return sortInfo;
|
|
21337
|
+
} else {
|
|
21338
|
+
for (let ii = 2; ii <= n; ii++) {
|
|
21339
|
+
const i = ii - 1;
|
|
21340
|
+
let k = i;
|
|
21341
|
+
let p2 = d[D(i)];
|
|
21342
|
+
for (let j = ii; j <= n; j++) {
|
|
21343
|
+
if (d[D(j)] < p2) {
|
|
21344
|
+
k = j;
|
|
21345
|
+
p2 = d[D(j)];
|
|
21346
|
+
}
|
|
21347
|
+
}
|
|
21348
|
+
if (k !== i) {
|
|
21349
|
+
d[D(k)] = d[D(i)];
|
|
21350
|
+
d[D(i)] = p2;
|
|
21351
|
+
dswap(n, z, Zc(i), 1, z, Zc(k), 1);
|
|
21352
|
+
}
|
|
21353
|
+
}
|
|
21354
|
+
}
|
|
21355
|
+
return info;
|
|
21356
|
+
}
|
|
21357
|
+
|
|
21358
|
+
// src/numbl-core/native/ts-lapack-eig-hermitian.ts
|
|
21359
|
+
var EPS2 = 2220446049250313e-31;
|
|
21360
|
+
var SAFMIN2 = 22250738585072014e-324;
|
|
21361
|
+
function dlapy3(x, y, z) {
|
|
21362
|
+
const w = Math.max(Math.abs(x), Math.abs(y), Math.abs(z));
|
|
21363
|
+
if (w === 0 || !Number.isFinite(w))
|
|
21364
|
+
return Math.abs(x) + Math.abs(y) + Math.abs(z);
|
|
21365
|
+
return w * Math.sqrt((x / w) ** 2 + (y / w) ** 2 + (z / w) ** 2);
|
|
21366
|
+
}
|
|
21367
|
+
function fsign7(mag2, s) {
|
|
21368
|
+
return s >= 0 ? Math.abs(mag2) : -Math.abs(mag2);
|
|
21369
|
+
}
|
|
21370
|
+
function cdiv2(ar, ai, br, bi) {
|
|
21371
|
+
if (Math.abs(br) >= Math.abs(bi)) {
|
|
21372
|
+
const r2 = bi / br;
|
|
21373
|
+
const t2 = br + bi * r2;
|
|
21374
|
+
return [(ar + ai * r2) / t2, (ai - ar * r2) / t2];
|
|
21375
|
+
}
|
|
21376
|
+
const r = br / bi;
|
|
21377
|
+
const t = br * r + bi;
|
|
21378
|
+
return [(ar * r + ai) / t, (ai * r - ar) / t];
|
|
21379
|
+
}
|
|
21380
|
+
function dznrm2(n, re, im, off, incx) {
|
|
21381
|
+
let scale = 0;
|
|
21382
|
+
let ssq = 1;
|
|
21383
|
+
for (let i = 0, k = off; i < n; i++, k += incx) {
|
|
21384
|
+
for (const v of [re[k], im[k]]) {
|
|
21385
|
+
if (v !== 0) {
|
|
21386
|
+
const a = Math.abs(v);
|
|
21387
|
+
if (scale < a) {
|
|
21388
|
+
ssq = 1 + ssq * (scale / a) ** 2;
|
|
21389
|
+
scale = a;
|
|
21390
|
+
} else {
|
|
21391
|
+
ssq += (a / scale) ** 2;
|
|
21392
|
+
}
|
|
21393
|
+
}
|
|
21394
|
+
}
|
|
21395
|
+
}
|
|
21396
|
+
return scale * Math.sqrt(ssq);
|
|
21397
|
+
}
|
|
21398
|
+
function zlarfg2(n, re, im, off, incx) {
|
|
21399
|
+
if (n <= 0) return { tauRe: 0, tauIm: 0 };
|
|
21400
|
+
let xnorm = dznrm2(n - 1, re, im, off + incx, incx);
|
|
21401
|
+
let alphr = re[off];
|
|
21402
|
+
let alphi = im[off];
|
|
21403
|
+
if (xnorm === 0 && alphi === 0) {
|
|
21404
|
+
return { tauRe: 0, tauIm: 0 };
|
|
21405
|
+
}
|
|
21406
|
+
let beta = -fsign7(dlapy3(alphr, alphi, xnorm), alphr);
|
|
21407
|
+
const safmin = SAFMIN2 / EPS2;
|
|
21408
|
+
const rsafmn = 1 / safmin;
|
|
21409
|
+
let knt = 0;
|
|
21410
|
+
if (Math.abs(beta) < safmin) {
|
|
21411
|
+
do {
|
|
21412
|
+
knt++;
|
|
21413
|
+
for (let i = 1, k = off + incx; i < n; i++, k += incx) {
|
|
21414
|
+
re[k] *= rsafmn;
|
|
21415
|
+
im[k] *= rsafmn;
|
|
21416
|
+
}
|
|
21417
|
+
beta *= rsafmn;
|
|
21418
|
+
alphi *= rsafmn;
|
|
21419
|
+
alphr *= rsafmn;
|
|
21420
|
+
} while (Math.abs(beta) < safmin && knt < 20);
|
|
21421
|
+
xnorm = dznrm2(n - 1, re, im, off + incx, incx);
|
|
21422
|
+
beta = -fsign7(dlapy3(alphr, alphi, xnorm), alphr);
|
|
21423
|
+
}
|
|
21424
|
+
const tauRe = (beta - alphr) / beta;
|
|
21425
|
+
const tauIm = -alphi / beta;
|
|
21426
|
+
const [sr, si] = cdiv2(1, 0, alphr - beta, alphi);
|
|
21427
|
+
for (let i = 1, k = off + incx; i < n; i++, k += incx) {
|
|
21428
|
+
const xr = re[k];
|
|
21429
|
+
const xi = im[k];
|
|
21430
|
+
re[k] = xr * sr - xi * si;
|
|
21431
|
+
im[k] = xr * si + xi * sr;
|
|
21432
|
+
}
|
|
21433
|
+
for (let j = 1; j <= knt; j++) beta *= safmin;
|
|
21434
|
+
re[off] = beta;
|
|
21435
|
+
im[off] = 0;
|
|
21436
|
+
return { tauRe, tauIm };
|
|
21437
|
+
}
|
|
21438
|
+
function zhemvLower(n, alphaRe, alphaIm, aRe, aIm, aOff, lda, xRe, xIm, xOff, yRe, yIm, yOff) {
|
|
21439
|
+
for (let i = 0; i < n; i++) {
|
|
21440
|
+
yRe[yOff + i] = 0;
|
|
21441
|
+
yIm[yOff + i] = 0;
|
|
21442
|
+
}
|
|
21443
|
+
for (let j = 0; j < n; j++) {
|
|
21444
|
+
const xjr = xRe[xOff + j];
|
|
21445
|
+
const xji = xIm[xOff + j];
|
|
21446
|
+
const t1r = alphaRe * xjr - alphaIm * xji;
|
|
21447
|
+
const t1i = alphaRe * xji + alphaIm * xjr;
|
|
21448
|
+
let t2r = 0;
|
|
21449
|
+
let t2i = 0;
|
|
21450
|
+
const col = aOff + j * lda;
|
|
21451
|
+
yRe[yOff + j] += t1r * aRe[col + j];
|
|
21452
|
+
yIm[yOff + j] += t1i * aRe[col + j];
|
|
21453
|
+
for (let i = j + 1; i < n; i++) {
|
|
21454
|
+
const ar = aRe[col + i];
|
|
21455
|
+
const ai = aIm[col + i];
|
|
21456
|
+
yRe[yOff + i] += t1r * ar - t1i * ai;
|
|
21457
|
+
yIm[yOff + i] += t1r * ai + t1i * ar;
|
|
21458
|
+
const xir = xRe[xOff + i];
|
|
21459
|
+
const xii = xIm[xOff + i];
|
|
21460
|
+
t2r += ar * xir + ai * xii;
|
|
21461
|
+
t2i += ar * xii - ai * xir;
|
|
21462
|
+
}
|
|
21463
|
+
yRe[yOff + j] += alphaRe * t2r - alphaIm * t2i;
|
|
21464
|
+
yIm[yOff + j] += alphaRe * t2i + alphaIm * t2r;
|
|
21465
|
+
}
|
|
21466
|
+
}
|
|
21467
|
+
function zher2LowerMinus(n, xRe, xIm, xOff, yRe, yIm, yOff, aRe, aIm, aOff, lda) {
|
|
21468
|
+
for (let j = 0; j < n; j++) {
|
|
21469
|
+
const xjr = xRe[xOff + j];
|
|
21470
|
+
const xji = xIm[xOff + j];
|
|
21471
|
+
const yjr = yRe[yOff + j];
|
|
21472
|
+
const yji = yIm[yOff + j];
|
|
21473
|
+
const col = aOff + j * lda;
|
|
21474
|
+
if (xjr !== 0 || xji !== 0 || yjr !== 0 || yji !== 0) {
|
|
21475
|
+
const t1r = -yjr;
|
|
21476
|
+
const t1i = yji;
|
|
21477
|
+
const t2r = -xjr;
|
|
21478
|
+
const t2i = xji;
|
|
21479
|
+
aRe[col + j] = aRe[col + j] + (xjr * t1r - xji * t1i) + (yjr * t2r - yji * t2i);
|
|
21480
|
+
aIm[col + j] = 0;
|
|
21481
|
+
for (let i = j + 1; i < n; i++) {
|
|
21482
|
+
const xir = xRe[xOff + i];
|
|
21483
|
+
const xii = xIm[xOff + i];
|
|
21484
|
+
const yir = yRe[yOff + i];
|
|
21485
|
+
const yii = yIm[yOff + i];
|
|
21486
|
+
aRe[col + i] += xir * t1r - xii * t1i + (yir * t2r - yii * t2i);
|
|
21487
|
+
aIm[col + i] += xir * t1i + xii * t1r + (yir * t2i + yii * t2r);
|
|
21488
|
+
}
|
|
21489
|
+
} else {
|
|
21490
|
+
aIm[col + j] = 0;
|
|
21491
|
+
}
|
|
21492
|
+
}
|
|
21493
|
+
}
|
|
21494
|
+
function zhetd2Lower(n, aRe, aIm, lda, d, e, tauRe, tauIm) {
|
|
21495
|
+
const wRe = allocFloat64Array(Math.max(1, n));
|
|
21496
|
+
const wIm = allocFloat64Array(Math.max(1, n));
|
|
21497
|
+
for (let i = 1; i <= n - 1; i++) {
|
|
21498
|
+
const off = i + (i - 1) * lda;
|
|
21499
|
+
const t = zlarfg2(n - i, aRe, aIm, off, 1);
|
|
21500
|
+
e[i - 1] = aRe[off];
|
|
21501
|
+
const taur = t.tauRe;
|
|
21502
|
+
const taui = t.tauIm;
|
|
21503
|
+
if (taur !== 0 || taui !== 0) {
|
|
21504
|
+
aRe[off] = 1;
|
|
21505
|
+
aIm[off] = 0;
|
|
21506
|
+
const m = n - i;
|
|
21507
|
+
const a11 = i + i * lda;
|
|
21508
|
+
zhemvLower(m, taur, taui, aRe, aIm, a11, lda, aRe, aIm, off, wRe, wIm, 0);
|
|
21509
|
+
let dr = 0;
|
|
21510
|
+
let di = 0;
|
|
21511
|
+
for (let k = 0; k < m; k++) {
|
|
21512
|
+
const vr = aRe[off + k];
|
|
21513
|
+
const vi = aIm[off + k];
|
|
21514
|
+
dr += wRe[k] * vr + wIm[k] * vi;
|
|
21515
|
+
di += wRe[k] * vi - wIm[k] * vr;
|
|
21516
|
+
}
|
|
21517
|
+
const ar = -0.5 * (taur * dr - taui * di);
|
|
21518
|
+
const ai = -0.5 * (taur * di + taui * dr);
|
|
21519
|
+
for (let k = 0; k < m; k++) {
|
|
21520
|
+
const vr = aRe[off + k];
|
|
21521
|
+
const vi = aIm[off + k];
|
|
21522
|
+
wRe[k] += ar * vr - ai * vi;
|
|
21523
|
+
wIm[k] += ar * vi + ai * vr;
|
|
21524
|
+
}
|
|
21525
|
+
zher2LowerMinus(m, aRe, aIm, off, wRe, wIm, 0, aRe, aIm, a11, lda);
|
|
21526
|
+
} else {
|
|
21527
|
+
const a11 = i + i * lda;
|
|
21528
|
+
aIm[a11] = 0;
|
|
21529
|
+
}
|
|
21530
|
+
aRe[off] = e[i - 1];
|
|
21531
|
+
aIm[off] = 0;
|
|
21532
|
+
d[i - 1] = aRe[i - 1 + (i - 1) * lda];
|
|
21533
|
+
tauRe[i - 1] = taur;
|
|
21534
|
+
tauIm[i - 1] = taui;
|
|
21535
|
+
}
|
|
21536
|
+
d[n - 1] = aRe[n - 1 + (n - 1) * lda];
|
|
21537
|
+
}
|
|
21538
|
+
function zungtrLower(n, aRe, aIm, lda, tauRe, tauIm) {
|
|
21539
|
+
for (let j = n; j >= 2; j--) {
|
|
21540
|
+
aRe[(j - 1) * lda] = 0;
|
|
21541
|
+
aIm[(j - 1) * lda] = 0;
|
|
21542
|
+
for (let i = j + 1; i <= n; i++) {
|
|
21543
|
+
aRe[i - 1 + (j - 1) * lda] = aRe[i - 1 + (j - 2) * lda];
|
|
21544
|
+
aIm[i - 1 + (j - 1) * lda] = aIm[i - 1 + (j - 2) * lda];
|
|
21545
|
+
}
|
|
21546
|
+
}
|
|
21547
|
+
aRe[0] = 1;
|
|
21548
|
+
aIm[0] = 0;
|
|
21549
|
+
for (let i = 2; i <= n; i++) {
|
|
21550
|
+
aRe[i - 1] = 0;
|
|
21551
|
+
aIm[i - 1] = 0;
|
|
21552
|
+
}
|
|
21553
|
+
if (n <= 1) return;
|
|
21554
|
+
const m = n - 1;
|
|
21555
|
+
const base = 1 + lda;
|
|
21556
|
+
const workRe = allocFloat64Array(Math.max(1, m));
|
|
21557
|
+
const workIm = allocFloat64Array(Math.max(1, m));
|
|
21558
|
+
for (let i = m; i >= 1; i--) {
|
|
21559
|
+
const vOff = base + (i - 1) + (i - 1) * lda;
|
|
21560
|
+
const tr = tauRe[i - 1];
|
|
21561
|
+
const ti = tauIm[i - 1];
|
|
21562
|
+
if (i < m) {
|
|
21563
|
+
aRe[vOff] = 1;
|
|
21564
|
+
aIm[vOff] = 0;
|
|
21565
|
+
const rows = m - i + 1;
|
|
21566
|
+
const cols = m - i;
|
|
21567
|
+
const cOff = base + (i - 1) + i * lda;
|
|
21568
|
+
for (let j = 0; j < cols; j++) {
|
|
21569
|
+
let sr = 0;
|
|
21570
|
+
let si = 0;
|
|
21571
|
+
for (let k = 0; k < rows; k++) {
|
|
21572
|
+
const cr = aRe[cOff + k + j * lda];
|
|
21573
|
+
const ci = aIm[cOff + k + j * lda];
|
|
21574
|
+
const vr = aRe[vOff + k];
|
|
21575
|
+
const vi = aIm[vOff + k];
|
|
21576
|
+
sr += cr * vr + ci * vi;
|
|
21577
|
+
si += cr * vi - ci * vr;
|
|
21578
|
+
}
|
|
21579
|
+
workRe[j] = sr;
|
|
21580
|
+
workIm[j] = si;
|
|
21581
|
+
}
|
|
21582
|
+
for (let j = 0; j < cols; j++) {
|
|
21583
|
+
const wr = workRe[j];
|
|
21584
|
+
const wi = -workIm[j];
|
|
21585
|
+
const fr = -(tr * wr - ti * wi);
|
|
21586
|
+
const fi = -(tr * wi + ti * wr);
|
|
21587
|
+
for (let k = 0; k < rows; k++) {
|
|
21588
|
+
const vr = aRe[vOff + k];
|
|
21589
|
+
const vi = aIm[vOff + k];
|
|
21590
|
+
aRe[cOff + k + j * lda] += fr * vr - fi * vi;
|
|
21591
|
+
aIm[cOff + k + j * lda] += fr * vi + fi * vr;
|
|
21592
|
+
}
|
|
21593
|
+
}
|
|
21594
|
+
}
|
|
21595
|
+
if (i < m) {
|
|
21596
|
+
for (let k = 1; k <= m - i; k++) {
|
|
21597
|
+
const vr = aRe[vOff + k];
|
|
21598
|
+
const vi = aIm[vOff + k];
|
|
21599
|
+
aRe[vOff + k] = -(tr * vr - ti * vi);
|
|
21600
|
+
aIm[vOff + k] = -(tr * vi + ti * vr);
|
|
21601
|
+
}
|
|
21602
|
+
}
|
|
21603
|
+
aRe[vOff] = 1 - tr;
|
|
21604
|
+
aIm[vOff] = -ti;
|
|
21605
|
+
for (let k = 1; k <= i - 1; k++) {
|
|
21606
|
+
aRe[base + (k - 1) + (i - 1) * lda] = 0;
|
|
21607
|
+
aIm[base + (k - 1) + (i - 1) * lda] = 0;
|
|
21608
|
+
}
|
|
21609
|
+
}
|
|
21610
|
+
}
|
|
21611
|
+
function eigHermTs(dataRe, dataIm, n, computeV) {
|
|
21612
|
+
const w = allocFloat64Array(n);
|
|
21613
|
+
if (n === 0)
|
|
21614
|
+
return { w, VRe: allocFloat64Array(0), VIm: allocFloat64Array(0) };
|
|
21615
|
+
if (n === 1) {
|
|
21616
|
+
w[0] = dataRe[0];
|
|
21617
|
+
if (!computeV) return { w };
|
|
21618
|
+
const VRe2 = allocFloat64Array(1);
|
|
21619
|
+
VRe2[0] = 1;
|
|
21620
|
+
return { w, VRe: VRe2, VIm: allocFloat64Array(1) };
|
|
21621
|
+
}
|
|
21622
|
+
const aRe = allocFloat64Array(dataRe);
|
|
21623
|
+
const aIm = allocFloat64Array(dataIm);
|
|
21624
|
+
const e = allocFloat64Array(Math.max(1, n - 1));
|
|
21625
|
+
const tauRe = allocFloat64Array(Math.max(1, n - 1));
|
|
21626
|
+
const tauIm = allocFloat64Array(Math.max(1, n - 1));
|
|
21627
|
+
zhetd2Lower(n, aRe, aIm, n, w, e, tauRe, tauIm);
|
|
21628
|
+
if (!computeV) {
|
|
21629
|
+
const work2 = allocFloat64Array(Math.max(1, 2 * n - 2));
|
|
21630
|
+
const dummy = allocFloat64Array(1);
|
|
21631
|
+
dsteqr(COMPZ_N, n, w, 0, e, 0, dummy, 0, 1, work2, 0);
|
|
21632
|
+
return { w };
|
|
21633
|
+
}
|
|
21634
|
+
zungtrLower(n, aRe, aIm, n, tauRe, tauIm);
|
|
21635
|
+
const S = allocFloat64Array(n * n);
|
|
21636
|
+
const work = allocFloat64Array(Math.max(1, 2 * n - 2));
|
|
21637
|
+
dsteqr(COMPZ_I, n, w, 0, e, 0, S, 0, n, work, 0);
|
|
21638
|
+
const VRe = allocFloat64Array(n * n);
|
|
21639
|
+
const VIm = allocFloat64Array(n * n);
|
|
21640
|
+
for (let j = 0; j < n; j++) {
|
|
21641
|
+
for (let k = 0; k < n; k++) {
|
|
21642
|
+
const s = S[k + j * n];
|
|
21643
|
+
if (s === 0) continue;
|
|
21644
|
+
for (let i = 0; i < n; i++) {
|
|
21645
|
+
VRe[i + j * n] += aRe[i + k * n] * s;
|
|
21646
|
+
VIm[i + j * n] += aIm[i + k * n] * s;
|
|
21647
|
+
}
|
|
21648
|
+
}
|
|
21649
|
+
}
|
|
21650
|
+
return { w, VRe, VIm };
|
|
21651
|
+
}
|
|
21652
|
+
|
|
21653
|
+
// src/ts-lapack/src/SRC/dlansy.ts
|
|
21654
|
+
var NORM_MAX7 = 0;
|
|
21655
|
+
var NORM_ONE3 = 1;
|
|
21656
|
+
var NORM_INF3 = 2;
|
|
21657
|
+
var NORM_FRO3 = 3;
|
|
21658
|
+
function dlansy(norm2, uplo, n, a, aOff, lda, work, workOff) {
|
|
21659
|
+
let value = 0;
|
|
21660
|
+
if (n === 0) {
|
|
21661
|
+
value = 0;
|
|
21662
|
+
} else if (norm2 === NORM_MAX7) {
|
|
21663
|
+
value = 0;
|
|
21664
|
+
if (uplo === UPPER) {
|
|
21665
|
+
for (let j = 1; j <= n; j++) {
|
|
21666
|
+
for (let i = 1; i <= j; i++) {
|
|
21667
|
+
const sum2 = Math.abs(a[aOff + (i - 1) + (j - 1) * lda]);
|
|
21668
|
+
if (value < sum2 || Number.isNaN(sum2)) value = sum2;
|
|
21669
|
+
}
|
|
21670
|
+
}
|
|
21671
|
+
} else {
|
|
21672
|
+
for (let j = 1; j <= n; j++) {
|
|
21673
|
+
for (let i = j; i <= n; i++) {
|
|
21674
|
+
const sum2 = Math.abs(a[aOff + (i - 1) + (j - 1) * lda]);
|
|
21675
|
+
if (value < sum2 || Number.isNaN(sum2)) value = sum2;
|
|
21676
|
+
}
|
|
21677
|
+
}
|
|
21678
|
+
}
|
|
21679
|
+
} else if (norm2 === NORM_ONE3 || norm2 === NORM_INF3) {
|
|
21680
|
+
value = 0;
|
|
21681
|
+
if (uplo === UPPER) {
|
|
21682
|
+
for (let j = 1; j <= n; j++) {
|
|
21683
|
+
let sum2 = 0;
|
|
21684
|
+
for (let i = 1; i <= j - 1; i++) {
|
|
21685
|
+
const absa = Math.abs(a[aOff + (i - 1) + (j - 1) * lda]);
|
|
21686
|
+
sum2 += absa;
|
|
21687
|
+
work[workOff + (i - 1)] += absa;
|
|
21688
|
+
}
|
|
21689
|
+
work[workOff + (j - 1)] = sum2 + Math.abs(a[aOff + (j - 1) + (j - 1) * lda]);
|
|
21690
|
+
}
|
|
21691
|
+
for (let i = 1; i <= n; i++) {
|
|
21692
|
+
const sum2 = work[workOff + (i - 1)];
|
|
21693
|
+
if (value < sum2 || Number.isNaN(sum2)) value = sum2;
|
|
21694
|
+
}
|
|
21695
|
+
} else {
|
|
21696
|
+
for (let i = 1; i <= n; i++) work[workOff + (i - 1)] = 0;
|
|
21697
|
+
for (let j = 1; j <= n; j++) {
|
|
21698
|
+
let sum2 = work[workOff + (j - 1)] + Math.abs(a[aOff + (j - 1) + (j - 1) * lda]);
|
|
21699
|
+
for (let i = j + 1; i <= n; i++) {
|
|
21700
|
+
const absa = Math.abs(a[aOff + (i - 1) + (j - 1) * lda]);
|
|
21701
|
+
sum2 += absa;
|
|
21702
|
+
work[workOff + (i - 1)] += absa;
|
|
21703
|
+
}
|
|
21704
|
+
if (value < sum2 || Number.isNaN(sum2)) value = sum2;
|
|
21705
|
+
}
|
|
21706
|
+
}
|
|
21707
|
+
} else if (norm2 === NORM_FRO3) {
|
|
21708
|
+
const scale = { val: 0 };
|
|
21709
|
+
const sum2 = { val: 1 };
|
|
21710
|
+
if (uplo === UPPER) {
|
|
21711
|
+
for (let j = 2; j <= n; j++) {
|
|
21712
|
+
dlassq(j - 1, a, aOff + (j - 1) * lda, 1, scale, sum2);
|
|
21713
|
+
}
|
|
21714
|
+
} else {
|
|
21715
|
+
for (let j = 1; j <= n - 1; j++) {
|
|
21716
|
+
dlassq(n - j, a, aOff + j + (j - 1) * lda, 1, scale, sum2);
|
|
21717
|
+
}
|
|
21718
|
+
}
|
|
21719
|
+
sum2.val = 2 * sum2.val;
|
|
21720
|
+
dlassq(n, a, aOff, lda + 1, scale, sum2);
|
|
21721
|
+
value = scale.val * Math.sqrt(sum2.val);
|
|
21722
|
+
}
|
|
21723
|
+
return value;
|
|
21724
|
+
}
|
|
21725
|
+
|
|
21726
|
+
// src/ts-lapack/src/BLAS/dsymv.ts
|
|
21727
|
+
function dsymv(uplo, n, alpha, a, aOff, lda, x, xOff, incx, beta, y, yOff, incy) {
|
|
21728
|
+
const ZERO9 = 0;
|
|
21729
|
+
const ONE10 = 1;
|
|
21730
|
+
let info = 0;
|
|
21731
|
+
if (uplo !== UPPER && uplo !== LOWER) {
|
|
21732
|
+
info = 1;
|
|
21733
|
+
} else if (n < 0) {
|
|
21734
|
+
info = 2;
|
|
21735
|
+
} else if (lda < Math.max(1, n)) {
|
|
21736
|
+
info = 5;
|
|
21737
|
+
} else if (incx === 0) {
|
|
21738
|
+
info = 7;
|
|
21739
|
+
} else if (incy === 0) {
|
|
21740
|
+
info = 10;
|
|
21741
|
+
}
|
|
21742
|
+
if (info !== 0) {
|
|
21743
|
+
xerbla("DSYMV ", info);
|
|
21744
|
+
return;
|
|
21745
|
+
}
|
|
21746
|
+
if (n === 0 || alpha === ZERO9 && beta === ONE10) return;
|
|
21747
|
+
const kx = incx > 0 ? 0 : -(n - 1) * incx;
|
|
21748
|
+
const ky = incy > 0 ? 0 : -(n - 1) * incy;
|
|
21749
|
+
if (beta !== ONE10) {
|
|
21750
|
+
let iy = ky;
|
|
21751
|
+
if (beta === ZERO9) {
|
|
21752
|
+
for (let i = 0; i < n; i++) {
|
|
21753
|
+
y[yOff + iy] = ZERO9;
|
|
21754
|
+
iy += incy;
|
|
21755
|
+
}
|
|
21756
|
+
} else {
|
|
21757
|
+
for (let i = 0; i < n; i++) {
|
|
21758
|
+
y[yOff + iy] *= beta;
|
|
21759
|
+
iy += incy;
|
|
21760
|
+
}
|
|
21761
|
+
}
|
|
21762
|
+
}
|
|
21763
|
+
if (alpha === ZERO9) return;
|
|
21764
|
+
if (uplo === UPPER) {
|
|
21765
|
+
let jx = kx;
|
|
21766
|
+
let jy = ky;
|
|
21767
|
+
for (let j = 1; j <= n; j++) {
|
|
21768
|
+
const temp1 = alpha * x[xOff + jx];
|
|
21769
|
+
let temp2 = ZERO9;
|
|
21770
|
+
const aCol = aOff + (j - 1) * lda;
|
|
21771
|
+
let ix = kx;
|
|
21772
|
+
let iy = ky;
|
|
21773
|
+
for (let i = 1; i <= j - 1; i++) {
|
|
21774
|
+
const aij = a[aCol + (i - 1)];
|
|
21775
|
+
y[yOff + iy] += temp1 * aij;
|
|
21776
|
+
temp2 += aij * x[xOff + ix];
|
|
21777
|
+
ix += incx;
|
|
21778
|
+
iy += incy;
|
|
21779
|
+
}
|
|
21780
|
+
y[yOff + jy] += temp1 * a[aCol + (j - 1)] + alpha * temp2;
|
|
21781
|
+
jx += incx;
|
|
21782
|
+
jy += incy;
|
|
21783
|
+
}
|
|
21784
|
+
} else {
|
|
21785
|
+
let jx = kx;
|
|
21786
|
+
let jy = ky;
|
|
21787
|
+
for (let j = 1; j <= n; j++) {
|
|
21788
|
+
const temp1 = alpha * x[xOff + jx];
|
|
21789
|
+
let temp2 = ZERO9;
|
|
21790
|
+
const aCol = aOff + (j - 1) * lda;
|
|
21791
|
+
y[yOff + jy] += temp1 * a[aCol + (j - 1)];
|
|
21792
|
+
let ix = jx;
|
|
21793
|
+
let iy = jy;
|
|
21794
|
+
for (let i = j + 1; i <= n; i++) {
|
|
21795
|
+
ix += incx;
|
|
21796
|
+
iy += incy;
|
|
21797
|
+
const aij = a[aCol + (i - 1)];
|
|
21798
|
+
y[yOff + iy] += temp1 * aij;
|
|
21799
|
+
temp2 += aij * x[xOff + ix];
|
|
21800
|
+
}
|
|
21801
|
+
y[yOff + jy] += alpha * temp2;
|
|
21802
|
+
jx += incx;
|
|
21803
|
+
jy += incy;
|
|
21804
|
+
}
|
|
21805
|
+
}
|
|
21806
|
+
}
|
|
21807
|
+
|
|
21808
|
+
// src/ts-lapack/src/BLAS/dsyr2.ts
|
|
21809
|
+
function dsyr2(uplo, n, alpha, x, xOff, incx, y, yOff, incy, a, aOff, lda) {
|
|
21810
|
+
const ZERO9 = 0;
|
|
21811
|
+
let info = 0;
|
|
21812
|
+
if (uplo !== UPPER && uplo !== LOWER) {
|
|
21813
|
+
info = 1;
|
|
21814
|
+
} else if (n < 0) {
|
|
21815
|
+
info = 2;
|
|
21816
|
+
} else if (incx === 0) {
|
|
21817
|
+
info = 5;
|
|
21818
|
+
} else if (incy === 0) {
|
|
21819
|
+
info = 7;
|
|
21820
|
+
} else if (lda < Math.max(1, n)) {
|
|
21821
|
+
info = 9;
|
|
21822
|
+
}
|
|
21823
|
+
if (info !== 0) {
|
|
21824
|
+
xerbla("DSYR2 ", info);
|
|
21825
|
+
return;
|
|
21826
|
+
}
|
|
21827
|
+
if (n === 0 || alpha === ZERO9) return;
|
|
21828
|
+
const kx = incx > 0 ? 0 : -(n - 1) * incx;
|
|
21829
|
+
const ky = incy > 0 ? 0 : -(n - 1) * incy;
|
|
21830
|
+
let jx = kx;
|
|
21831
|
+
let jy = ky;
|
|
21832
|
+
if (uplo === UPPER) {
|
|
21833
|
+
for (let j = 1; j <= n; j++) {
|
|
21834
|
+
const xj = x[xOff + jx];
|
|
21835
|
+
const yj = y[yOff + jy];
|
|
21836
|
+
if (xj !== ZERO9 || yj !== ZERO9) {
|
|
21837
|
+
const temp1 = alpha * yj;
|
|
21838
|
+
const temp2 = alpha * xj;
|
|
21839
|
+
const aCol = aOff + (j - 1) * lda;
|
|
21840
|
+
let ix = kx;
|
|
21841
|
+
let iy = ky;
|
|
21842
|
+
for (let i = 1; i <= j; i++) {
|
|
21843
|
+
a[aCol + (i - 1)] += x[xOff + ix] * temp1 + y[yOff + iy] * temp2;
|
|
21844
|
+
ix += incx;
|
|
21845
|
+
iy += incy;
|
|
21846
|
+
}
|
|
21847
|
+
}
|
|
21848
|
+
jx += incx;
|
|
21849
|
+
jy += incy;
|
|
21850
|
+
}
|
|
21851
|
+
} else {
|
|
21852
|
+
for (let j = 1; j <= n; j++) {
|
|
21853
|
+
const xj = x[xOff + jx];
|
|
21854
|
+
const yj = y[yOff + jy];
|
|
21855
|
+
if (xj !== ZERO9 || yj !== ZERO9) {
|
|
21856
|
+
const temp1 = alpha * yj;
|
|
21857
|
+
const temp2 = alpha * xj;
|
|
21858
|
+
const aCol = aOff + (j - 1) * lda;
|
|
21859
|
+
let ix = jx;
|
|
21860
|
+
let iy = jy;
|
|
21861
|
+
for (let i = j; i <= n; i++) {
|
|
21862
|
+
a[aCol + (i - 1)] += x[xOff + ix] * temp1 + y[yOff + iy] * temp2;
|
|
21863
|
+
ix += incx;
|
|
21864
|
+
iy += incy;
|
|
21865
|
+
}
|
|
21866
|
+
}
|
|
21867
|
+
jx += incx;
|
|
21868
|
+
jy += incy;
|
|
21869
|
+
}
|
|
21870
|
+
}
|
|
21871
|
+
}
|
|
21872
|
+
|
|
21873
|
+
// src/ts-lapack/src/SRC/dsytd2.ts
|
|
21874
|
+
function dsytd2(uplo, n, a, aOff, lda, d, dOff, e, eOff, tau, tauOff) {
|
|
21875
|
+
const ONE10 = 1;
|
|
21876
|
+
const ZERO9 = 0;
|
|
21877
|
+
const HALF = 0.5;
|
|
21878
|
+
let info = 0;
|
|
21879
|
+
const upper = uplo === UPPER;
|
|
21880
|
+
if (!upper && uplo !== LOWER) {
|
|
21881
|
+
info = -1;
|
|
21882
|
+
} else if (n < 0) {
|
|
21883
|
+
info = -2;
|
|
21884
|
+
} else if (lda < Math.max(1, n)) {
|
|
21885
|
+
info = -4;
|
|
21886
|
+
}
|
|
21887
|
+
if (info !== 0) {
|
|
21888
|
+
xerbla("DSYTD2", -info);
|
|
21889
|
+
return info;
|
|
21890
|
+
}
|
|
21891
|
+
if (n <= 0) return 0;
|
|
21892
|
+
const A = (i, j) => aOff + (i - 1) + (j - 1) * lda;
|
|
21893
|
+
if (upper) {
|
|
21894
|
+
for (let i = n - 1; i >= 1; i--) {
|
|
21895
|
+
const r = dlarfg(i, a[A(i, i + 1)], a, A(1, i + 1), 1);
|
|
21896
|
+
a[A(i, i + 1)] = r.alpha;
|
|
21897
|
+
const taui = r.tau;
|
|
21898
|
+
e[eOff + (i - 1)] = a[A(i, i + 1)];
|
|
21899
|
+
if (taui !== ZERO9) {
|
|
21900
|
+
a[A(i, i + 1)] = ONE10;
|
|
21901
|
+
dsymv(
|
|
21902
|
+
uplo,
|
|
21903
|
+
i,
|
|
21904
|
+
taui,
|
|
21905
|
+
a,
|
|
21906
|
+
aOff,
|
|
21907
|
+
lda,
|
|
21908
|
+
a,
|
|
21909
|
+
A(1, i + 1),
|
|
21910
|
+
1,
|
|
21911
|
+
ZERO9,
|
|
21912
|
+
tau,
|
|
21913
|
+
tauOff,
|
|
21914
|
+
1
|
|
21915
|
+
);
|
|
21916
|
+
const alpha = -HALF * taui * ddot(i, tau, tauOff, 1, a, A(1, i + 1), 1);
|
|
21917
|
+
daxpy(i, alpha, a, A(1, i + 1), 1, tau, tauOff, 1);
|
|
21918
|
+
dsyr2(uplo, i, -ONE10, a, A(1, i + 1), 1, tau, tauOff, 1, a, aOff, lda);
|
|
21919
|
+
a[A(i, i + 1)] = e[eOff + (i - 1)];
|
|
21920
|
+
}
|
|
21921
|
+
d[dOff + i] = a[A(i + 1, i + 1)];
|
|
21922
|
+
tau[tauOff + (i - 1)] = taui;
|
|
21923
|
+
}
|
|
21924
|
+
d[dOff] = a[A(1, 1)];
|
|
21925
|
+
} else {
|
|
21926
|
+
for (let i = 1; i <= n - 1; i++) {
|
|
21927
|
+
const r = dlarfg(n - i, a[A(i + 1, i)], a, A(Math.min(i + 2, n), i), 1);
|
|
21928
|
+
a[A(i + 1, i)] = r.alpha;
|
|
21929
|
+
const taui = r.tau;
|
|
21930
|
+
e[eOff + (i - 1)] = a[A(i + 1, i)];
|
|
21931
|
+
if (taui !== ZERO9) {
|
|
21932
|
+
a[A(i + 1, i)] = ONE10;
|
|
21933
|
+
dsymv(
|
|
21934
|
+
uplo,
|
|
21935
|
+
n - i,
|
|
21936
|
+
taui,
|
|
21937
|
+
a,
|
|
21938
|
+
A(i + 1, i + 1),
|
|
21939
|
+
lda,
|
|
21940
|
+
a,
|
|
21941
|
+
A(i + 1, i),
|
|
21942
|
+
1,
|
|
21943
|
+
ZERO9,
|
|
21944
|
+
tau,
|
|
21945
|
+
tauOff + (i - 1),
|
|
21946
|
+
1
|
|
21947
|
+
);
|
|
21948
|
+
const alpha = -HALF * taui * ddot(n - i, tau, tauOff + (i - 1), 1, a, A(i + 1, i), 1);
|
|
21949
|
+
daxpy(n - i, alpha, a, A(i + 1, i), 1, tau, tauOff + (i - 1), 1);
|
|
21950
|
+
dsyr2(
|
|
21951
|
+
uplo,
|
|
21952
|
+
n - i,
|
|
21953
|
+
-ONE10,
|
|
21954
|
+
a,
|
|
21955
|
+
A(i + 1, i),
|
|
21956
|
+
1,
|
|
21957
|
+
tau,
|
|
21958
|
+
tauOff + (i - 1),
|
|
21959
|
+
1,
|
|
21960
|
+
a,
|
|
21961
|
+
A(i + 1, i + 1),
|
|
21962
|
+
lda
|
|
21963
|
+
);
|
|
21964
|
+
a[A(i + 1, i)] = e[eOff + (i - 1)];
|
|
21965
|
+
}
|
|
21966
|
+
d[dOff + (i - 1)] = a[A(i, i)];
|
|
21967
|
+
tau[tauOff + (i - 1)] = taui;
|
|
21968
|
+
}
|
|
21969
|
+
d[dOff + (n - 1)] = a[A(n, n)];
|
|
21970
|
+
}
|
|
21971
|
+
return 0;
|
|
21972
|
+
}
|
|
21973
|
+
|
|
21974
|
+
// src/ts-lapack/src/SRC/dorgtr.ts
|
|
21975
|
+
function dorgtr(uplo, n, a, aOff, lda, tau, tauOff) {
|
|
21976
|
+
const ONE10 = 1;
|
|
21977
|
+
const ZERO9 = 0;
|
|
21978
|
+
let info = 0;
|
|
21979
|
+
if (uplo !== LOWER) {
|
|
21980
|
+
info = -1;
|
|
21981
|
+
} else if (n < 0) {
|
|
21982
|
+
info = -2;
|
|
21983
|
+
} else if (lda < Math.max(1, n)) {
|
|
21984
|
+
info = -4;
|
|
21985
|
+
}
|
|
21986
|
+
if (info !== 0) {
|
|
21987
|
+
xerbla("DORGTR", -info);
|
|
21988
|
+
return info;
|
|
21989
|
+
}
|
|
21990
|
+
if (n === 0) return 0;
|
|
21991
|
+
const A = (i, j) => aOff + (i - 1) + (j - 1) * lda;
|
|
21992
|
+
for (let j = n; j >= 2; j--) {
|
|
21993
|
+
a[A(1, j)] = ZERO9;
|
|
21994
|
+
for (let i = j + 1; i <= n; i++) {
|
|
21995
|
+
a[A(i, j)] = a[A(i, j - 1)];
|
|
21996
|
+
}
|
|
21997
|
+
}
|
|
21998
|
+
a[A(1, 1)] = ONE10;
|
|
21999
|
+
for (let i = 2; i <= n; i++) {
|
|
22000
|
+
a[A(i, 1)] = ZERO9;
|
|
22001
|
+
}
|
|
22002
|
+
if (n > 1) {
|
|
22003
|
+
info = dorgqr(n - 1, n - 1, n - 1, a, A(2, 2), lda, tau, tauOff);
|
|
22004
|
+
}
|
|
22005
|
+
return info;
|
|
22006
|
+
}
|
|
22007
|
+
|
|
22008
|
+
// src/ts-lapack/src/SRC/dsyev.ts
|
|
22009
|
+
var NORM_MAX8 = 0;
|
|
22010
|
+
var TYPE_L2 = 1;
|
|
22011
|
+
function dsyev(wantz, uplo, n, a, aOff, lda, w, wOff) {
|
|
22012
|
+
const ONE10 = 1;
|
|
22013
|
+
const ZERO9 = 0;
|
|
22014
|
+
let info = 0;
|
|
22015
|
+
if (uplo !== LOWER) {
|
|
22016
|
+
info = -2;
|
|
22017
|
+
} else if (n < 0) {
|
|
22018
|
+
info = -3;
|
|
22019
|
+
} else if (lda < Math.max(1, n)) {
|
|
22020
|
+
info = -5;
|
|
22021
|
+
}
|
|
22022
|
+
if (info !== 0) {
|
|
22023
|
+
xerbla("DSYEV ", -info);
|
|
22024
|
+
return info;
|
|
22025
|
+
}
|
|
22026
|
+
if (n === 0) return 0;
|
|
22027
|
+
if (n === 1) {
|
|
22028
|
+
w[wOff] = a[aOff];
|
|
22029
|
+
if (wantz) a[aOff] = ONE10;
|
|
22030
|
+
return 0;
|
|
22031
|
+
}
|
|
22032
|
+
const safmin = dlamch(MACH_SFMIN);
|
|
22033
|
+
const eps2 = dlamch(MACH_PREC);
|
|
22034
|
+
const smlnum = safmin / eps2;
|
|
22035
|
+
const bignum = ONE10 / smlnum;
|
|
22036
|
+
const rmin = Math.sqrt(smlnum);
|
|
22037
|
+
const rmax = Math.sqrt(bignum);
|
|
22038
|
+
const work = allocFloat64Array(Math.max(1, 3 * n));
|
|
22039
|
+
const anrm = dlansy(NORM_MAX8, uplo, n, a, aOff, lda, work, 0);
|
|
22040
|
+
let iscale = 0;
|
|
22041
|
+
let sigma = ONE10;
|
|
22042
|
+
if (anrm > ZERO9 && anrm < rmin) {
|
|
22043
|
+
iscale = 1;
|
|
22044
|
+
sigma = rmin / anrm;
|
|
22045
|
+
} else if (anrm > rmax) {
|
|
22046
|
+
iscale = 1;
|
|
22047
|
+
sigma = rmax / anrm;
|
|
22048
|
+
}
|
|
22049
|
+
if (iscale === 1) dlascl(TYPE_L2, 0, 0, ONE10, sigma, n, n, a, aOff, lda);
|
|
22050
|
+
const e = allocFloat64Array(Math.max(1, n - 1));
|
|
22051
|
+
const tau = allocFloat64Array(Math.max(1, n - 1));
|
|
22052
|
+
dsytd2(uplo, n, a, aOff, lda, w, wOff, e, 0, tau, 0);
|
|
22053
|
+
if (!wantz) {
|
|
22054
|
+
info = dsteqr(COMPZ_N, n, w, wOff, e, 0, a, aOff, lda, work, 0);
|
|
22055
|
+
} else {
|
|
22056
|
+
const iinfo = dorgtr(uplo, n, a, aOff, lda, tau, 0);
|
|
22057
|
+
if (iinfo !== 0) return iinfo;
|
|
22058
|
+
info = dsteqr(COMPZ_V, n, w, wOff, e, 0, a, aOff, lda, work, 0);
|
|
22059
|
+
}
|
|
22060
|
+
if (iscale === 1) {
|
|
22061
|
+
const imax = info === 0 ? n : info - 1;
|
|
22062
|
+
dscal(imax, ONE10 / sigma, w, wOff, 1);
|
|
22063
|
+
}
|
|
22064
|
+
return info;
|
|
22065
|
+
}
|
|
22066
|
+
|
|
20696
22067
|
// src/numbl-core/native/ts-lapack-bridge.ts
|
|
20697
22068
|
function inv(data, n) {
|
|
20698
22069
|
const a = allocFloat64Array(data);
|
|
@@ -20866,6 +22237,20 @@ function linsolve(A, m, n, B, nrhs) {
|
|
|
20866
22237
|
return x;
|
|
20867
22238
|
}
|
|
20868
22239
|
}
|
|
22240
|
+
function eigSym(data, n, computeV) {
|
|
22241
|
+
const a = allocFloat64Array(data);
|
|
22242
|
+
const w = allocFloat64Array(n);
|
|
22243
|
+
const info = dsyev(computeV, LOWER, n, a, 0, n, w, 0);
|
|
22244
|
+
if (info !== 0) {
|
|
22245
|
+
throw new Error(
|
|
22246
|
+
info < 0 ? "eig: illegal argument passed to dsyev" : "QR algorithm failed to converge in dsyev"
|
|
22247
|
+
);
|
|
22248
|
+
}
|
|
22249
|
+
return computeV ? { w, V: a } : { w };
|
|
22250
|
+
}
|
|
22251
|
+
function eigHerm(dataRe, dataIm, n, computeV) {
|
|
22252
|
+
return eigHermTs(dataRe, dataIm, n, computeV);
|
|
22253
|
+
}
|
|
20869
22254
|
function eig(data, n, computeVL, computeVR, balance) {
|
|
20870
22255
|
const a = allocFloat64Array(data);
|
|
20871
22256
|
const wr = allocFloat64Array(n);
|
|
@@ -21604,7 +22989,9 @@ var _bridge2 = {
|
|
|
21604
22989
|
linsolve,
|
|
21605
22990
|
linsolveComplex,
|
|
21606
22991
|
eig,
|
|
22992
|
+
eigSym,
|
|
21607
22993
|
eigComplex: eigComplexTs,
|
|
22994
|
+
eigHerm,
|
|
21608
22995
|
lu,
|
|
21609
22996
|
svd,
|
|
21610
22997
|
chol,
|
|
@@ -22053,6 +23440,7 @@ function formatClassInstance(v) {
|
|
|
22053
23440
|
const lines = [` ${v.className} with properties:
|
|
22054
23441
|
`];
|
|
22055
23442
|
for (const [key, val] of v.fields) {
|
|
23443
|
+
if (key.startsWith("_")) continue;
|
|
22056
23444
|
lines.push(` ${key}: ${displayValue(val)}`);
|
|
22057
23445
|
}
|
|
22058
23446
|
return lines.join("\n");
|
|
@@ -27756,6 +29144,707 @@ function sprintfFormat(fmt, args) {
|
|
|
27756
29144
|
return result;
|
|
27757
29145
|
}
|
|
27758
29146
|
|
|
29147
|
+
// src/numbl-core/helpers/warn.ts
|
|
29148
|
+
var sink = (msg) => console.warn("Warning: " + msg);
|
|
29149
|
+
function setWarningSink(fn) {
|
|
29150
|
+
sink = fn;
|
|
29151
|
+
}
|
|
29152
|
+
function emitWarning(msg) {
|
|
29153
|
+
sink(msg);
|
|
29154
|
+
}
|
|
29155
|
+
|
|
29156
|
+
// src/numbl-core/helpers/sparse-direct.ts
|
|
29157
|
+
var SINGULAR_WARNING = "Matrix is singular to working precision.";
|
|
29158
|
+
function denseToSparse(t) {
|
|
29159
|
+
const m = t.shape[0] ?? 1;
|
|
29160
|
+
const n = t.shape.length >= 2 ? t.shape[1] : 1;
|
|
29161
|
+
const irList = [];
|
|
29162
|
+
const prList = [];
|
|
29163
|
+
const piList = t.imag ? [] : void 0;
|
|
29164
|
+
const jc = new Int32Array(n + 1);
|
|
29165
|
+
for (let c = 0; c < n; c++) {
|
|
29166
|
+
jc[c] = irList.length;
|
|
29167
|
+
for (let r = 0; r < m; r++) {
|
|
29168
|
+
const idx = c * m + r;
|
|
29169
|
+
const re = t.data[idx];
|
|
29170
|
+
const im = t.imag ? t.imag[idx] : 0;
|
|
29171
|
+
if (re !== 0 || im !== 0) {
|
|
29172
|
+
irList.push(r);
|
|
29173
|
+
prList.push(re);
|
|
29174
|
+
if (piList) piList.push(im);
|
|
29175
|
+
}
|
|
29176
|
+
}
|
|
29177
|
+
}
|
|
29178
|
+
jc[n] = irList.length;
|
|
29179
|
+
return RTV.sparseMatrix(
|
|
29180
|
+
m,
|
|
29181
|
+
n,
|
|
29182
|
+
new Int32Array(irList),
|
|
29183
|
+
jc,
|
|
29184
|
+
allocFloat64Array(prList),
|
|
29185
|
+
piList ? allocFloat64Array(piList) : void 0
|
|
29186
|
+
);
|
|
29187
|
+
}
|
|
29188
|
+
function denseDataToSparse(data, m, n) {
|
|
29189
|
+
return denseToSparse(RTV.tensor(data, [m, n]));
|
|
29190
|
+
}
|
|
29191
|
+
function fromUnsortedColumns(m, n, ir, jc, pr) {
|
|
29192
|
+
return sparseTranspose(sparseTranspose(RTV.sparseMatrix(m, n, ir, jc, pr)));
|
|
29193
|
+
}
|
|
29194
|
+
function permutationMatrix(p2) {
|
|
29195
|
+
const n = p2.length;
|
|
29196
|
+
const ir = new Int32Array(n);
|
|
29197
|
+
const jc = new Int32Array(n + 1);
|
|
29198
|
+
const pr = allocFloat64Array(n);
|
|
29199
|
+
for (let k = 0; k < n; k++) jc[p2[k] + 1]++;
|
|
29200
|
+
for (let c = 0; c < n; c++) jc[c + 1] += jc[c];
|
|
29201
|
+
for (let k = 0; k < n; k++) {
|
|
29202
|
+
ir[jc[p2[k]]] = k;
|
|
29203
|
+
pr[jc[p2[k]]] = 1;
|
|
29204
|
+
}
|
|
29205
|
+
return RTV.sparseMatrix(n, n, ir, jc, pr);
|
|
29206
|
+
}
|
|
29207
|
+
function permVectorTensor(p2) {
|
|
29208
|
+
const d = allocFloat64Array(p2.length);
|
|
29209
|
+
for (let i = 0; i < p2.length; i++) d[i] = p2[i] + 1;
|
|
29210
|
+
return RTV.tensor(d, [1, p2.length]);
|
|
29211
|
+
}
|
|
29212
|
+
function invertPerm(p2) {
|
|
29213
|
+
const inv2 = new Int32Array(p2.length);
|
|
29214
|
+
for (let i = 0; i < p2.length; i++) inv2[p2[i]] = i;
|
|
29215
|
+
return inv2;
|
|
29216
|
+
}
|
|
29217
|
+
function sparsePermute(A, p2, q) {
|
|
29218
|
+
const pinv = invertPerm(p2);
|
|
29219
|
+
const nnz = A.jc[A.n];
|
|
29220
|
+
const ir = new Int32Array(nnz);
|
|
29221
|
+
const jc = new Int32Array(A.n + 1);
|
|
29222
|
+
const pr = allocFloat64Array(nnz);
|
|
29223
|
+
let pos = 0;
|
|
29224
|
+
for (let k = 0; k < A.n; k++) {
|
|
29225
|
+
jc[k] = pos;
|
|
29226
|
+
const j = q[k];
|
|
29227
|
+
for (let t = A.jc[j]; t < A.jc[j + 1]; t++) {
|
|
29228
|
+
ir[pos] = pinv[A.ir[t]];
|
|
29229
|
+
pr[pos] = A.pr[t];
|
|
29230
|
+
pos++;
|
|
29231
|
+
}
|
|
29232
|
+
}
|
|
29233
|
+
jc[A.n] = pos;
|
|
29234
|
+
return fromUnsortedColumns(A.m, A.n, ir, jc, pr);
|
|
29235
|
+
}
|
|
29236
|
+
function sparseKron(A, B) {
|
|
29237
|
+
const m = A.m, n = A.n, p2 = B.m, q = B.n;
|
|
29238
|
+
const nnz = A.jc[n] * B.jc[q];
|
|
29239
|
+
const ir = new Int32Array(nnz);
|
|
29240
|
+
const jc = new Int32Array(n * q + 1);
|
|
29241
|
+
const pr = allocFloat64Array(nnz);
|
|
29242
|
+
const cplx = A.pi !== void 0 || B.pi !== void 0;
|
|
29243
|
+
const pi2 = cplx ? allocFloat64Array(nnz) : void 0;
|
|
29244
|
+
let pos = 0;
|
|
29245
|
+
for (let ja = 0; ja < n; ja++) {
|
|
29246
|
+
for (let jb = 0; jb < q; jb++) {
|
|
29247
|
+
jc[ja * q + jb] = pos;
|
|
29248
|
+
for (let ka = A.jc[ja]; ka < A.jc[ja + 1]; ka++) {
|
|
29249
|
+
const rowBase = A.ir[ka] * p2;
|
|
29250
|
+
const aRe = A.pr[ka];
|
|
29251
|
+
const aIm = A.pi ? A.pi[ka] : 0;
|
|
29252
|
+
for (let kb = B.jc[jb]; kb < B.jc[jb + 1]; kb++) {
|
|
29253
|
+
ir[pos] = rowBase + B.ir[kb];
|
|
29254
|
+
const bRe = B.pr[kb];
|
|
29255
|
+
const bIm = B.pi ? B.pi[kb] : 0;
|
|
29256
|
+
pr[pos] = aRe * bRe - aIm * bIm;
|
|
29257
|
+
if (pi2) pi2[pos] = aRe * bIm + aIm * bRe;
|
|
29258
|
+
pos++;
|
|
29259
|
+
}
|
|
29260
|
+
}
|
|
29261
|
+
}
|
|
29262
|
+
}
|
|
29263
|
+
jc[n * q] = pos;
|
|
29264
|
+
return RTV.sparseMatrix(m * p2, n * q, ir, jc, pr, pi2);
|
|
29265
|
+
}
|
|
29266
|
+
function triangularInfo(S) {
|
|
29267
|
+
if (S._triInfo) return S._triInfo;
|
|
29268
|
+
const n = S.n;
|
|
29269
|
+
const ir = S.ir, jc = S.jc, pr = S.pr, pi2 = S.pi;
|
|
29270
|
+
const diagPos = new Int32Array(n).fill(-1);
|
|
29271
|
+
const diag2 = allocFloat64Array(n);
|
|
29272
|
+
let upper = true;
|
|
29273
|
+
let lower = true;
|
|
29274
|
+
for (let j = 0; j < n; j++) {
|
|
29275
|
+
const end = jc[j + 1];
|
|
29276
|
+
for (let k = jc[j]; k < end; k++) {
|
|
29277
|
+
const i = ir[k];
|
|
29278
|
+
if (i === j) {
|
|
29279
|
+
diagPos[j] = k;
|
|
29280
|
+
diag2[j] = pr[k];
|
|
29281
|
+
continue;
|
|
29282
|
+
}
|
|
29283
|
+
if (pr[k] === 0 && (!pi2 || pi2[k] === 0)) continue;
|
|
29284
|
+
if (i > j) upper = false;
|
|
29285
|
+
else lower = false;
|
|
29286
|
+
}
|
|
29287
|
+
}
|
|
29288
|
+
const info = { upper, lower, diagPos, diag: diag2 };
|
|
29289
|
+
S._triInfo = info;
|
|
29290
|
+
return info;
|
|
29291
|
+
}
|
|
29292
|
+
function sparseIsUpper(S) {
|
|
29293
|
+
return triangularInfo(S).upper;
|
|
29294
|
+
}
|
|
29295
|
+
function sparseIsLower(S) {
|
|
29296
|
+
return triangularInfo(S).lower;
|
|
29297
|
+
}
|
|
29298
|
+
function sparseIsSymmetric(S) {
|
|
29299
|
+
if (S.m !== S.n || S.pi) return false;
|
|
29300
|
+
const T = sparseTranspose(S);
|
|
29301
|
+
const nnz = S.jc[S.n];
|
|
29302
|
+
if (T.jc[T.n] !== nnz) return false;
|
|
29303
|
+
for (let j = 0; j <= S.n; j++) if (S.jc[j] !== T.jc[j]) return false;
|
|
29304
|
+
for (let k = 0; k < nnz; k++)
|
|
29305
|
+
if (S.ir[k] !== T.ir[k] || S.pr[k] !== T.pr[k]) return false;
|
|
29306
|
+
return true;
|
|
29307
|
+
}
|
|
29308
|
+
function sparseAt(S, i, j) {
|
|
29309
|
+
let lo = S.jc[j], hi = S.jc[j + 1] - 1;
|
|
29310
|
+
while (lo <= hi) {
|
|
29311
|
+
const mid = lo + hi >> 1;
|
|
29312
|
+
const r = S.ir[mid];
|
|
29313
|
+
if (r === i) return S.pr[mid];
|
|
29314
|
+
if (r < i) lo = mid + 1;
|
|
29315
|
+
else hi = mid - 1;
|
|
29316
|
+
}
|
|
29317
|
+
return 0;
|
|
29318
|
+
}
|
|
29319
|
+
function allDiagPositive(S) {
|
|
29320
|
+
for (let j = 0; j < S.n; j++) if (!(sparseAt(S, j, j) > 0)) return false;
|
|
29321
|
+
return true;
|
|
29322
|
+
}
|
|
29323
|
+
function sparseSolveUpper(R, B, nrhs) {
|
|
29324
|
+
const n = R.n;
|
|
29325
|
+
const { diagPos, diag: diag2 } = triangularInfo(R);
|
|
29326
|
+
const ir = R.ir, jc = R.jc, pr = R.pr;
|
|
29327
|
+
const x = allocFloat64Array(B);
|
|
29328
|
+
let singular = false;
|
|
29329
|
+
for (let j = 0; j < n; j++) if (diag2[j] === 0) singular = true;
|
|
29330
|
+
for (let c = 0; c < nrhs; c++) {
|
|
29331
|
+
const off = c * n;
|
|
29332
|
+
for (let j = n - 1; j >= 0; j--) {
|
|
29333
|
+
const xj = x[off + j] / diag2[j];
|
|
29334
|
+
x[off + j] = xj;
|
|
29335
|
+
if (xj === 0) continue;
|
|
29336
|
+
const dp = diagPos[j];
|
|
29337
|
+
const end = dp >= 0 ? dp : jc[j + 1];
|
|
29338
|
+
for (let k = jc[j]; k < end; k++) x[off + ir[k]] -= pr[k] * xj;
|
|
29339
|
+
}
|
|
29340
|
+
}
|
|
29341
|
+
return { x, singular };
|
|
29342
|
+
}
|
|
29343
|
+
function sparseSolveLower(L, B, nrhs) {
|
|
29344
|
+
const n = L.n;
|
|
29345
|
+
const { diagPos, diag: diag2 } = triangularInfo(L);
|
|
29346
|
+
const ir = L.ir, jc = L.jc, pr = L.pr;
|
|
29347
|
+
const x = allocFloat64Array(B);
|
|
29348
|
+
let singular = false;
|
|
29349
|
+
for (let j = 0; j < n; j++) if (diag2[j] === 0) singular = true;
|
|
29350
|
+
for (let c = 0; c < nrhs; c++) {
|
|
29351
|
+
const off = c * n;
|
|
29352
|
+
for (let j = 0; j < n; j++) {
|
|
29353
|
+
const xj = x[off + j] / diag2[j];
|
|
29354
|
+
x[off + j] = xj;
|
|
29355
|
+
if (xj === 0) continue;
|
|
29356
|
+
const dp = diagPos[j];
|
|
29357
|
+
const end = jc[j + 1];
|
|
29358
|
+
for (let k = dp >= 0 ? dp + 1 : jc[j]; k < end; k++)
|
|
29359
|
+
x[off + ir[k]] -= pr[k] * xj;
|
|
29360
|
+
}
|
|
29361
|
+
}
|
|
29362
|
+
return { x, singular };
|
|
29363
|
+
}
|
|
29364
|
+
function permuteRows(X, n, nrhs, p2) {
|
|
29365
|
+
const Y = allocFloat64Array(X.length);
|
|
29366
|
+
for (let c = 0; c < nrhs; c++) {
|
|
29367
|
+
const off = c * n;
|
|
29368
|
+
for (let k = 0; k < n; k++) Y[off + k] = X[off + p2[k]];
|
|
29369
|
+
}
|
|
29370
|
+
return Y;
|
|
29371
|
+
}
|
|
29372
|
+
function unpermuteRows(X, n, nrhs, p2) {
|
|
29373
|
+
const Y = allocFloat64Array(X.length);
|
|
29374
|
+
for (let c = 0; c < nrhs; c++) {
|
|
29375
|
+
const off = c * n;
|
|
29376
|
+
for (let k = 0; k < n; k++) Y[off + p2[k]] = X[off + k];
|
|
29377
|
+
}
|
|
29378
|
+
return Y;
|
|
29379
|
+
}
|
|
29380
|
+
function eliminationTree(A) {
|
|
29381
|
+
const n = A.n;
|
|
29382
|
+
const parent = new Int32Array(n).fill(-1);
|
|
29383
|
+
const ancestor = new Int32Array(n).fill(-1);
|
|
29384
|
+
for (let k = 0; k < n; k++) {
|
|
29385
|
+
for (let p2 = A.jc[k]; p2 < A.jc[k + 1]; p2++) {
|
|
29386
|
+
let i = A.ir[p2];
|
|
29387
|
+
while (i !== -1 && i < k) {
|
|
29388
|
+
const inext = ancestor[i];
|
|
29389
|
+
ancestor[i] = k;
|
|
29390
|
+
if (inext === -1) parent[i] = k;
|
|
29391
|
+
i = inext;
|
|
29392
|
+
}
|
|
29393
|
+
}
|
|
29394
|
+
}
|
|
29395
|
+
return parent;
|
|
29396
|
+
}
|
|
29397
|
+
function etreeReach(A, k, parent, s, mark) {
|
|
29398
|
+
const n = A.n;
|
|
29399
|
+
let top = n;
|
|
29400
|
+
mark[k] = k;
|
|
29401
|
+
for (let p2 = A.jc[k]; p2 < A.jc[k + 1]; p2++) {
|
|
29402
|
+
let i = A.ir[p2];
|
|
29403
|
+
if (i > k) continue;
|
|
29404
|
+
let len = 0;
|
|
29405
|
+
for (; mark[i] !== k; i = parent[i]) {
|
|
29406
|
+
s[len++] = i;
|
|
29407
|
+
mark[i] = k;
|
|
29408
|
+
}
|
|
29409
|
+
while (len > 0) s[--top] = s[--len];
|
|
29410
|
+
}
|
|
29411
|
+
return top;
|
|
29412
|
+
}
|
|
29413
|
+
function sparseChol(A) {
|
|
29414
|
+
const n = A.n;
|
|
29415
|
+
if (A.m !== n) throw new RuntimeError("chol: Matrix must be square.");
|
|
29416
|
+
const parent = eliminationTree(A);
|
|
29417
|
+
const s = new Int32Array(n);
|
|
29418
|
+
const mark = new Int32Array(n).fill(-1);
|
|
29419
|
+
const colCount = new Int32Array(n);
|
|
29420
|
+
for (let k = 0; k < n; k++) {
|
|
29421
|
+
const top = etreeReach(A, k, parent, s, mark);
|
|
29422
|
+
for (let t = top; t < n; t++) colCount[s[t]]++;
|
|
29423
|
+
colCount[k]++;
|
|
29424
|
+
}
|
|
29425
|
+
const Lp = new Int32Array(n + 1);
|
|
29426
|
+
for (let j = 0; j < n; j++) Lp[j + 1] = Lp[j] + colCount[j];
|
|
29427
|
+
const nnzL = Lp[n];
|
|
29428
|
+
const Li = new Int32Array(nnzL);
|
|
29429
|
+
const Lx = allocFloat64Array(nnzL);
|
|
29430
|
+
const c = new Int32Array(n);
|
|
29431
|
+
for (let j = 0; j < n; j++) c[j] = Lp[j];
|
|
29432
|
+
const x = allocFloat64Array(n);
|
|
29433
|
+
mark.fill(-1);
|
|
29434
|
+
for (let k = 0; k < n; k++) {
|
|
29435
|
+
const top = etreeReach(A, k, parent, s, mark);
|
|
29436
|
+
x[k] = 0;
|
|
29437
|
+
for (let p2 = A.jc[k]; p2 < A.jc[k + 1]; p2++) {
|
|
29438
|
+
if (A.ir[p2] <= k) x[A.ir[p2]] = A.pr[p2];
|
|
29439
|
+
}
|
|
29440
|
+
let d = x[k];
|
|
29441
|
+
x[k] = 0;
|
|
29442
|
+
for (let t = top; t < n; t++) {
|
|
29443
|
+
const i = s[t];
|
|
29444
|
+
const lki = x[i] / Lx[Lp[i]];
|
|
29445
|
+
x[i] = 0;
|
|
29446
|
+
for (let p2 = Lp[i] + 1; p2 < c[i]; p2++) x[Li[p2]] -= Lx[p2] * lki;
|
|
29447
|
+
d -= lki * lki;
|
|
29448
|
+
const pos2 = c[i]++;
|
|
29449
|
+
Li[pos2] = k;
|
|
29450
|
+
Lx[pos2] = lki;
|
|
29451
|
+
}
|
|
29452
|
+
if (!(d > 0)) {
|
|
29453
|
+
for (let i = k + 1; i < n; i++) {
|
|
29454
|
+
const top2 = etreeReach(A, i, parent, s, mark);
|
|
29455
|
+
for (let p2 = A.jc[i]; p2 < A.jc[i + 1]; p2++)
|
|
29456
|
+
if (A.ir[p2] < k) x[A.ir[p2]] = A.pr[p2];
|
|
29457
|
+
for (let t = top2; t < n; t++) {
|
|
29458
|
+
const j = s[t];
|
|
29459
|
+
if (j >= k) {
|
|
29460
|
+
x[j] = 0;
|
|
29461
|
+
continue;
|
|
29462
|
+
}
|
|
29463
|
+
const lij = x[j] / Lx[Lp[j]];
|
|
29464
|
+
x[j] = 0;
|
|
29465
|
+
for (let p2 = Lp[j] + 1; p2 < c[j]; p2++) x[Li[p2]] -= Lx[p2] * lij;
|
|
29466
|
+
const pos2 = c[j]++;
|
|
29467
|
+
Li[pos2] = i;
|
|
29468
|
+
Lx[pos2] = lij;
|
|
29469
|
+
}
|
|
29470
|
+
}
|
|
29471
|
+
return { L: leadingColumns(n, k, Lp, Li, Lx, c), ok: false, p: k + 1 };
|
|
29472
|
+
}
|
|
29473
|
+
const pos = c[k]++;
|
|
29474
|
+
Li[pos] = k;
|
|
29475
|
+
Lx[pos] = Math.sqrt(d);
|
|
29476
|
+
}
|
|
29477
|
+
return { L: RTV.sparseMatrix(n, n, Li, Lp, Lx), ok: true, p: 0 };
|
|
29478
|
+
}
|
|
29479
|
+
function leadingColumns(n, k, Lp, Li, Lx, c) {
|
|
29480
|
+
let nnz = 0;
|
|
29481
|
+
for (let j = 0; j < k; j++) nnz += c[j] - Lp[j];
|
|
29482
|
+
const ir = new Int32Array(nnz);
|
|
29483
|
+
const pr = allocFloat64Array(nnz);
|
|
29484
|
+
const jc = new Int32Array(k + 1);
|
|
29485
|
+
let pos = 0;
|
|
29486
|
+
for (let j = 0; j < k; j++) {
|
|
29487
|
+
jc[j] = pos;
|
|
29488
|
+
for (let p2 = Lp[j]; p2 < c[j]; p2++) {
|
|
29489
|
+
ir[pos] = Li[p2];
|
|
29490
|
+
pr[pos] = Lx[p2];
|
|
29491
|
+
pos++;
|
|
29492
|
+
}
|
|
29493
|
+
}
|
|
29494
|
+
jc[k] = pos;
|
|
29495
|
+
return RTV.sparseMatrix(n, k, ir, jc, pr);
|
|
29496
|
+
}
|
|
29497
|
+
function sparseLu(A, q, tol) {
|
|
29498
|
+
const m = A.m, n = A.n;
|
|
29499
|
+
const kmin = Math.min(m, n);
|
|
29500
|
+
const Lp = [0];
|
|
29501
|
+
const Li = [];
|
|
29502
|
+
const Lx = [];
|
|
29503
|
+
const Up = [0];
|
|
29504
|
+
const Ui = [];
|
|
29505
|
+
const Ux = [];
|
|
29506
|
+
const pinv = new Int32Array(m).fill(-1);
|
|
29507
|
+
const x = allocFloat64Array(m);
|
|
29508
|
+
const xi = new Int32Array(m);
|
|
29509
|
+
const stack = new Int32Array(m);
|
|
29510
|
+
const pstack = new Int32Array(m);
|
|
29511
|
+
const mark = new Int32Array(m).fill(-1);
|
|
29512
|
+
let singular = false;
|
|
29513
|
+
for (let k = 0; k < n; k++) {
|
|
29514
|
+
const col = q ? q[k] : k;
|
|
29515
|
+
let top = m;
|
|
29516
|
+
for (let t = A.jc[col]; t < A.jc[col + 1]; t++) {
|
|
29517
|
+
const i0 = A.ir[t];
|
|
29518
|
+
if (mark[i0] === k) continue;
|
|
29519
|
+
let head = 0;
|
|
29520
|
+
stack[0] = i0;
|
|
29521
|
+
mark[i0] = k;
|
|
29522
|
+
pstack[i0] = pinv[i0] >= 0 ? Lp[pinv[i0]] : -1;
|
|
29523
|
+
while (head >= 0) {
|
|
29524
|
+
const j = stack[head];
|
|
29525
|
+
const J = pinv[j];
|
|
29526
|
+
let descended = false;
|
|
29527
|
+
if (J >= 0) {
|
|
29528
|
+
const end = Lp[J + 1];
|
|
29529
|
+
let p3 = pstack[j];
|
|
29530
|
+
for (; p3 < end; p3++) {
|
|
29531
|
+
const i = Li[p3];
|
|
29532
|
+
if (mark[i] !== k) {
|
|
29533
|
+
mark[i] = k;
|
|
29534
|
+
pstack[j] = p3 + 1;
|
|
29535
|
+
stack[++head] = i;
|
|
29536
|
+
pstack[i] = pinv[i] >= 0 ? Lp[pinv[i]] : -1;
|
|
29537
|
+
descended = true;
|
|
29538
|
+
break;
|
|
29539
|
+
}
|
|
29540
|
+
}
|
|
29541
|
+
if (descended) continue;
|
|
29542
|
+
}
|
|
29543
|
+
head--;
|
|
29544
|
+
xi[--top] = j;
|
|
29545
|
+
}
|
|
29546
|
+
}
|
|
29547
|
+
for (let t = A.jc[col]; t < A.jc[col + 1]; t++) x[A.ir[t]] = A.pr[t];
|
|
29548
|
+
for (let t = top; t < m; t++) {
|
|
29549
|
+
const j = xi[t];
|
|
29550
|
+
const J = pinv[j];
|
|
29551
|
+
if (J < 0) continue;
|
|
29552
|
+
const xj = x[j];
|
|
29553
|
+
if (xj === 0) continue;
|
|
29554
|
+
for (let p3 = Lp[J] + 1; p3 < Lp[J + 1]; p3++) x[Li[p3]] -= Lx[p3] * xj;
|
|
29555
|
+
}
|
|
29556
|
+
let ipiv = -1;
|
|
29557
|
+
let amax = -1;
|
|
29558
|
+
for (let t = top; t < m; t++) {
|
|
29559
|
+
const i = xi[t];
|
|
29560
|
+
if (pinv[i] >= 0) {
|
|
29561
|
+
Ui.push(pinv[i]);
|
|
29562
|
+
Ux.push(x[i]);
|
|
29563
|
+
} else {
|
|
29564
|
+
const a = Math.abs(x[i]);
|
|
29565
|
+
if (a > amax) {
|
|
29566
|
+
amax = a;
|
|
29567
|
+
ipiv = i;
|
|
29568
|
+
}
|
|
29569
|
+
}
|
|
29570
|
+
}
|
|
29571
|
+
if (k < kmin) {
|
|
29572
|
+
if (ipiv < 0 || amax === 0) {
|
|
29573
|
+
singular = true;
|
|
29574
|
+
if (ipiv < 0) {
|
|
29575
|
+
for (let i = 0; i < m; i++)
|
|
29576
|
+
if (pinv[i] < 0) {
|
|
29577
|
+
ipiv = i;
|
|
29578
|
+
break;
|
|
29579
|
+
}
|
|
29580
|
+
}
|
|
29581
|
+
} else if (col < m && pinv[col] < 0 && Math.abs(x[col]) >= tol * amax && x[col] !== 0) {
|
|
29582
|
+
ipiv = col;
|
|
29583
|
+
}
|
|
29584
|
+
const pivot = x[ipiv];
|
|
29585
|
+
if (!Number.isFinite(pivot)) singular = true;
|
|
29586
|
+
pinv[ipiv] = k;
|
|
29587
|
+
Ui.push(k);
|
|
29588
|
+
Ux.push(pivot);
|
|
29589
|
+
Li.push(ipiv);
|
|
29590
|
+
Lx.push(1);
|
|
29591
|
+
if (pivot !== 0 && Number.isFinite(pivot)) {
|
|
29592
|
+
for (let t = top; t < m; t++) {
|
|
29593
|
+
const i = xi[t];
|
|
29594
|
+
if (pinv[i] >= 0) continue;
|
|
29595
|
+
const v = x[i] / pivot;
|
|
29596
|
+
if (v !== 0) {
|
|
29597
|
+
Li.push(i);
|
|
29598
|
+
Lx.push(v);
|
|
29599
|
+
}
|
|
29600
|
+
}
|
|
29601
|
+
}
|
|
29602
|
+
Lp.push(Li.length);
|
|
29603
|
+
}
|
|
29604
|
+
Up.push(Ui.length);
|
|
29605
|
+
for (let t = top; t < m; t++) x[xi[t]] = 0;
|
|
29606
|
+
}
|
|
29607
|
+
let next = kmin;
|
|
29608
|
+
for (let i = 0; i < m; i++) if (pinv[i] < 0) pinv[i] = next++;
|
|
29609
|
+
const LiArr = new Int32Array(Li.length);
|
|
29610
|
+
for (let p3 = 0; p3 < Li.length; p3++) LiArr[p3] = pinv[Li[p3]];
|
|
29611
|
+
const L = fromUnsortedColumns(
|
|
29612
|
+
m,
|
|
29613
|
+
kmin,
|
|
29614
|
+
LiArr,
|
|
29615
|
+
new Int32Array(Lp),
|
|
29616
|
+
allocFloat64Array(Lx)
|
|
29617
|
+
);
|
|
29618
|
+
const U = fromUnsortedColumns(
|
|
29619
|
+
kmin,
|
|
29620
|
+
n,
|
|
29621
|
+
new Int32Array(Ui),
|
|
29622
|
+
new Int32Array(Up),
|
|
29623
|
+
allocFloat64Array(Ux)
|
|
29624
|
+
);
|
|
29625
|
+
const p2 = invertPerm(pinv);
|
|
29626
|
+
const qOut = q ? Int32Array.from(q) : identityPerm(n);
|
|
29627
|
+
return { L, U, p: p2, q: qOut, singular };
|
|
29628
|
+
}
|
|
29629
|
+
function identityPerm(n) {
|
|
29630
|
+
const p2 = new Int32Array(n);
|
|
29631
|
+
for (let i = 0; i < n; i++) p2[i] = i;
|
|
29632
|
+
return p2;
|
|
29633
|
+
}
|
|
29634
|
+
function symmetricAdjacency(A) {
|
|
29635
|
+
const n = Math.max(A.m, A.n);
|
|
29636
|
+
const adj = new Array(n);
|
|
29637
|
+
for (let i = 0; i < n; i++) adj[i] = /* @__PURE__ */ new Set();
|
|
29638
|
+
for (let j = 0; j < A.n; j++)
|
|
29639
|
+
for (let k = A.jc[j]; k < A.jc[j + 1]; k++) {
|
|
29640
|
+
const i = A.ir[k];
|
|
29641
|
+
if (i === j) continue;
|
|
29642
|
+
adj[i].add(j);
|
|
29643
|
+
adj[j].add(i);
|
|
29644
|
+
}
|
|
29645
|
+
return adj;
|
|
29646
|
+
}
|
|
29647
|
+
function minimumDegreeOrdering(A) {
|
|
29648
|
+
const adj = symmetricAdjacency(A);
|
|
29649
|
+
const n = adj.length;
|
|
29650
|
+
const perm = new Int32Array(n);
|
|
29651
|
+
if (n === 0) return perm;
|
|
29652
|
+
const head = new Int32Array(n + 1).fill(-1);
|
|
29653
|
+
const next = new Int32Array(n).fill(-1);
|
|
29654
|
+
const prev = new Int32Array(n).fill(-1);
|
|
29655
|
+
const deg = new Int32Array(n);
|
|
29656
|
+
const insert = (v) => {
|
|
29657
|
+
const d = deg[v];
|
|
29658
|
+
next[v] = head[d];
|
|
29659
|
+
prev[v] = -1;
|
|
29660
|
+
if (head[d] >= 0) prev[head[d]] = v;
|
|
29661
|
+
head[d] = v;
|
|
29662
|
+
};
|
|
29663
|
+
const remove = (v) => {
|
|
29664
|
+
const d = deg[v];
|
|
29665
|
+
if (prev[v] >= 0) next[prev[v]] = next[v];
|
|
29666
|
+
else head[d] = next[v];
|
|
29667
|
+
if (next[v] >= 0) prev[next[v]] = prev[v];
|
|
29668
|
+
};
|
|
29669
|
+
for (let v = 0; v < n; v++) {
|
|
29670
|
+
deg[v] = adj[v].size;
|
|
29671
|
+
insert(v);
|
|
29672
|
+
}
|
|
29673
|
+
let mind = 0;
|
|
29674
|
+
for (let step = 0; step < n; step++) {
|
|
29675
|
+
while (head[mind] < 0) mind++;
|
|
29676
|
+
const v = head[mind];
|
|
29677
|
+
remove(v);
|
|
29678
|
+
perm[step] = v;
|
|
29679
|
+
const nbrs = Array.from(adj[v]);
|
|
29680
|
+
for (const u of nbrs) adj[u].delete(v);
|
|
29681
|
+
for (let a = 0; a < nbrs.length; a++) {
|
|
29682
|
+
const u = nbrs[a];
|
|
29683
|
+
const su = adj[u];
|
|
29684
|
+
for (let b = a + 1; b < nbrs.length; b++) {
|
|
29685
|
+
const w = nbrs[b];
|
|
29686
|
+
if (!su.has(w)) {
|
|
29687
|
+
su.add(w);
|
|
29688
|
+
adj[w].add(u);
|
|
29689
|
+
}
|
|
29690
|
+
}
|
|
29691
|
+
}
|
|
29692
|
+
for (const u of nbrs) {
|
|
29693
|
+
remove(u);
|
|
29694
|
+
deg[u] = adj[u].size;
|
|
29695
|
+
insert(u);
|
|
29696
|
+
if (deg[u] < mind) mind = deg[u];
|
|
29697
|
+
}
|
|
29698
|
+
adj[v].clear();
|
|
29699
|
+
}
|
|
29700
|
+
return perm;
|
|
29701
|
+
}
|
|
29702
|
+
function reverseCuthillMcKee(A) {
|
|
29703
|
+
const adj = symmetricAdjacency(A);
|
|
29704
|
+
const n = adj.length;
|
|
29705
|
+
const nb = adj.map(
|
|
29706
|
+
(s) => Array.from(s).sort((a, b) => adj[a].size - adj[b].size || a - b)
|
|
29707
|
+
);
|
|
29708
|
+
const visited = new Uint8Array(n);
|
|
29709
|
+
const order = [];
|
|
29710
|
+
const bfsLevels = (start) => {
|
|
29711
|
+
const seen = new Uint8Array(n);
|
|
29712
|
+
let frontier = [start];
|
|
29713
|
+
seen[start] = 1;
|
|
29714
|
+
let levels = 0;
|
|
29715
|
+
let last = start;
|
|
29716
|
+
while (frontier.length > 0) {
|
|
29717
|
+
const nextF = [];
|
|
29718
|
+
for (const u of frontier)
|
|
29719
|
+
for (const w of nb[u])
|
|
29720
|
+
if (!seen[w]) {
|
|
29721
|
+
seen[w] = 1;
|
|
29722
|
+
nextF.push(w);
|
|
29723
|
+
}
|
|
29724
|
+
if (nextF.length === 0) {
|
|
29725
|
+
last = frontier.reduce((a, b) => adj[b].size < adj[a].size ? b : a);
|
|
29726
|
+
break;
|
|
29727
|
+
}
|
|
29728
|
+
frontier = nextF;
|
|
29729
|
+
levels++;
|
|
29730
|
+
}
|
|
29731
|
+
return { last, levels };
|
|
29732
|
+
};
|
|
29733
|
+
for (let s0 = 0; s0 < n; s0++) {
|
|
29734
|
+
if (visited[s0]) continue;
|
|
29735
|
+
let start = s0;
|
|
29736
|
+
let info = bfsLevels(start);
|
|
29737
|
+
for (let iter = 0; iter < 4; iter++) {
|
|
29738
|
+
const cand = bfsLevels(info.last);
|
|
29739
|
+
if (cand.levels > info.levels) {
|
|
29740
|
+
start = info.last;
|
|
29741
|
+
info = cand;
|
|
29742
|
+
} else {
|
|
29743
|
+
start = info.last;
|
|
29744
|
+
break;
|
|
29745
|
+
}
|
|
29746
|
+
}
|
|
29747
|
+
const queue = [start];
|
|
29748
|
+
visited[start] = 1;
|
|
29749
|
+
let qh = 0;
|
|
29750
|
+
while (qh < queue.length) {
|
|
29751
|
+
const u = queue[qh++];
|
|
29752
|
+
order.push(u);
|
|
29753
|
+
for (const w of nb[u])
|
|
29754
|
+
if (!visited[w]) {
|
|
29755
|
+
visited[w] = 1;
|
|
29756
|
+
queue.push(w);
|
|
29757
|
+
}
|
|
29758
|
+
}
|
|
29759
|
+
}
|
|
29760
|
+
const perm = new Int32Array(n);
|
|
29761
|
+
for (let i = 0; i < n; i++) perm[i] = order[n - 1 - i];
|
|
29762
|
+
return perm;
|
|
29763
|
+
}
|
|
29764
|
+
function ataPattern(A) {
|
|
29765
|
+
const At = sparseTranspose(A);
|
|
29766
|
+
const n = A.n;
|
|
29767
|
+
const marker = new Int32Array(n).fill(-1);
|
|
29768
|
+
const ir = [];
|
|
29769
|
+
const jc = new Int32Array(n + 1);
|
|
29770
|
+
for (let j = 0; j < n; j++) {
|
|
29771
|
+
jc[j] = ir.length;
|
|
29772
|
+
for (let k = A.jc[j]; k < A.jc[j + 1]; k++) {
|
|
29773
|
+
const row = A.ir[k];
|
|
29774
|
+
for (let t = At.jc[row]; t < At.jc[row + 1]; t++) {
|
|
29775
|
+
const i = At.ir[t];
|
|
29776
|
+
if (marker[i] !== j) {
|
|
29777
|
+
marker[i] = j;
|
|
29778
|
+
ir.push(i);
|
|
29779
|
+
}
|
|
29780
|
+
}
|
|
29781
|
+
}
|
|
29782
|
+
}
|
|
29783
|
+
jc[n] = ir.length;
|
|
29784
|
+
const pr = allocFloat64Array(ir.length).fill(1);
|
|
29785
|
+
return fromUnsortedColumns(n, n, new Int32Array(ir), jc, pr);
|
|
29786
|
+
}
|
|
29787
|
+
function columnOrdering(A) {
|
|
29788
|
+
return minimumDegreeOrdering(ataPattern(A));
|
|
29789
|
+
}
|
|
29790
|
+
var DENSE_FRACTION = 0.5;
|
|
29791
|
+
function sparseSolve(A, B, nrhs) {
|
|
29792
|
+
const n = A.n;
|
|
29793
|
+
if (A.m !== n || A.pi) return null;
|
|
29794
|
+
if (n === 0) return allocFloat64Array(0);
|
|
29795
|
+
const nnz = A.jc[n];
|
|
29796
|
+
if (nnz > DENSE_FRACTION * n * n && n > 8) return null;
|
|
29797
|
+
if (sparseIsUpper(A)) {
|
|
29798
|
+
const r = sparseSolveUpper(A, B, nrhs);
|
|
29799
|
+
if (r.singular) emitWarning(SINGULAR_WARNING);
|
|
29800
|
+
return r.x;
|
|
29801
|
+
}
|
|
29802
|
+
if (sparseIsLower(A)) {
|
|
29803
|
+
const r = sparseSolveLower(A, B, nrhs);
|
|
29804
|
+
if (r.singular) emitWarning(SINGULAR_WARNING);
|
|
29805
|
+
return r.x;
|
|
29806
|
+
}
|
|
29807
|
+
const perm = reverseCuthillMcKee(A);
|
|
29808
|
+
if (sparseIsSymmetric(A) && allDiagPositive(A)) {
|
|
29809
|
+
const Ap = sparsePermute(A, perm, perm);
|
|
29810
|
+
const ch = sparseChol(Ap);
|
|
29811
|
+
if (ch.ok) {
|
|
29812
|
+
const Lt = sparseTranspose(ch.L);
|
|
29813
|
+
const bp = permuteRows(B, n, nrhs, perm);
|
|
29814
|
+
const y = sparseSolveLower(ch.L, bp, nrhs).x;
|
|
29815
|
+
const z = sparseSolveUpper(Lt, y, nrhs).x;
|
|
29816
|
+
return unpermuteRows(z, n, nrhs, perm);
|
|
29817
|
+
}
|
|
29818
|
+
}
|
|
29819
|
+
const lu2 = sparseLu(A, perm, 1);
|
|
29820
|
+
return luSolve(lu2, B, nrhs);
|
|
29821
|
+
}
|
|
29822
|
+
function luSolve(lu2, B, nrhs) {
|
|
29823
|
+
const n = lu2.U.n;
|
|
29824
|
+
const pb = permuteRows(B, n, nrhs, lu2.p);
|
|
29825
|
+
const y = sparseSolveLower(lu2.L, pb, nrhs);
|
|
29826
|
+
const z = sparseSolveUpper(lu2.U, y.x, nrhs);
|
|
29827
|
+
if (lu2.singular || z.singular) emitWarning(SINGULAR_WARNING);
|
|
29828
|
+
return unpermuteRows(z.x, n, nrhs, lu2.q);
|
|
29829
|
+
}
|
|
29830
|
+
function luSolveTransposed(lu2, B, nrhs) {
|
|
29831
|
+
const n = lu2.U.n;
|
|
29832
|
+
const qb = permuteRows(B, n, nrhs, lu2.q);
|
|
29833
|
+
const y = sparseSolveLower(sparseTranspose(lu2.U), qb, nrhs);
|
|
29834
|
+
const z = sparseSolveUpper(sparseTranspose(lu2.L), y.x, nrhs);
|
|
29835
|
+
if (lu2.singular || y.singular) emitWarning(SINGULAR_WARNING);
|
|
29836
|
+
return unpermuteRows(z.x, n, nrhs, lu2.p);
|
|
29837
|
+
}
|
|
29838
|
+
function sparseInverse(A) {
|
|
29839
|
+
const n = A.n;
|
|
29840
|
+
if (A.m !== n) throw new RuntimeError("inv: matrix must be square");
|
|
29841
|
+
const I = allocFloat64Array(n * n);
|
|
29842
|
+
for (let i = 0; i < n; i++) I[i + i * n] = 1;
|
|
29843
|
+
const X = sparseSolve(A, I, n);
|
|
29844
|
+
if (X === null) throw new RuntimeError("inv: unsupported sparse matrix");
|
|
29845
|
+
return denseDataToSparse(X, n, n);
|
|
29846
|
+
}
|
|
29847
|
+
|
|
27759
29848
|
// src/numbl-core/helpers/arithmetic.ts
|
|
27760
29849
|
function toComplex(v) {
|
|
27761
29850
|
if (isRuntimeComplexNumber(v)) return { re: v.re, im: v.im };
|
|
@@ -28346,6 +30435,12 @@ function mElemMul(a, b) {
|
|
|
28346
30435
|
}
|
|
28347
30436
|
function mDiv(a, b) {
|
|
28348
30437
|
if (isRuntimeSparseMatrix(a) || isRuntimeSparseMatrix(b)) {
|
|
30438
|
+
if (isRuntimeSparseMatrix(a) && (isRuntimeNumber(b) || isRuntimeLogical(b) || isRuntimeComplexNumber(b) || isRuntimeTensor(b) && b.data.length === 1))
|
|
30439
|
+
return mElemDivSparse(a, b);
|
|
30440
|
+
if (isRuntimeSparseMatrix(b) && !(b.m === 1 && b.n === 1)) {
|
|
30441
|
+
const result = mLeftDiv(mConjugateTranspose(b), mConjugateTranspose(a));
|
|
30442
|
+
return mConjugateTranspose(result);
|
|
30443
|
+
}
|
|
28349
30444
|
return mDiv(densify(a), densify(b));
|
|
28350
30445
|
}
|
|
28351
30446
|
if (isRuntimeTensor(a) && a.data.length === 1) a = unwrap1x1(a);
|
|
@@ -28401,8 +30496,50 @@ function mElemDiv(a, b) {
|
|
|
28401
30496
|
}
|
|
28402
30497
|
return binaryOp(a, b, (x, y) => x / y, BIN_OP_DIV);
|
|
28403
30498
|
}
|
|
30499
|
+
function sparseLeftDiv(A, b) {
|
|
30500
|
+
if (A.pi) return null;
|
|
30501
|
+
if (A.m === 1 && A.n === 1) return null;
|
|
30502
|
+
let B;
|
|
30503
|
+
let rows, nrhs;
|
|
30504
|
+
const bSparse = isRuntimeSparseMatrix(b);
|
|
30505
|
+
if (isRuntimeSparseMatrix(b)) {
|
|
30506
|
+
if (b.pi) return null;
|
|
30507
|
+
const d = sparseToDense(b);
|
|
30508
|
+
B = d.data;
|
|
30509
|
+
rows = b.m;
|
|
30510
|
+
nrhs = b.n;
|
|
30511
|
+
} else if (isRuntimeTensor(b)) {
|
|
30512
|
+
if (b.imag) return null;
|
|
30513
|
+
[rows, nrhs] = tensorSize2D(b);
|
|
30514
|
+
B = b.data;
|
|
30515
|
+
} else if (isRuntimeNumber(b) || isRuntimeLogical(b)) {
|
|
30516
|
+
B = allocFloat64Array([toNumber(b)]);
|
|
30517
|
+
rows = 1;
|
|
30518
|
+
nrhs = 1;
|
|
30519
|
+
} else {
|
|
30520
|
+
return null;
|
|
30521
|
+
}
|
|
30522
|
+
if (rows !== A.m)
|
|
30523
|
+
throw new RuntimeError(
|
|
30524
|
+
`mldivide (\\): A is ${A.m}\xD7${A.n} but B has ${rows} rows`
|
|
30525
|
+
);
|
|
30526
|
+
if (A.m !== A.n) {
|
|
30527
|
+
emitWarning(
|
|
30528
|
+
"mldivide: sparse least-squares uses a dense factorization; the sparse matrix is converted to full."
|
|
30529
|
+
);
|
|
30530
|
+
return null;
|
|
30531
|
+
}
|
|
30532
|
+
const X = sparseSolve(A, B, nrhs);
|
|
30533
|
+
if (X === null) return null;
|
|
30534
|
+
if (bSparse) return denseDataToSparse(X, A.n, nrhs);
|
|
30535
|
+
return unwrap1x1(RTV.tensor(X, [A.n, nrhs]));
|
|
30536
|
+
}
|
|
28404
30537
|
function mLeftDiv(a, b) {
|
|
28405
|
-
if (isRuntimeSparseMatrix(a))
|
|
30538
|
+
if (isRuntimeSparseMatrix(a)) {
|
|
30539
|
+
const r = sparseLeftDiv(a, b);
|
|
30540
|
+
if (r !== null) return r;
|
|
30541
|
+
return mLeftDiv(densify(a), densify(b));
|
|
30542
|
+
}
|
|
28406
30543
|
if (isRuntimeSparseMatrix(b)) return mLeftDiv(a, densify(b));
|
|
28407
30544
|
if (isRuntimeTensor(a) && a.data.length === 1) a = unwrap1x1(a);
|
|
28408
30545
|
if (isRuntimeTensor(b) && b.data.length === 1) b = unwrap1x1(b);
|
|
@@ -29489,7 +31626,7 @@ function applyUnaryElemwiseMaybeComplex(v, realFn, complexFn, name, nativeOpCode
|
|
|
29489
31626
|
if (typeof v === "boolean") v = v ? 1 : 0;
|
|
29490
31627
|
if (typeof v === "number") {
|
|
29491
31628
|
const r = realFn(v);
|
|
29492
|
-
if (!Number.isNaN(r)) return r;
|
|
31629
|
+
if (!Number.isNaN(r) || Number.isNaN(v)) return r;
|
|
29493
31630
|
const c = complexFn(v, 0);
|
|
29494
31631
|
return mkc(c.re, c.im);
|
|
29495
31632
|
}
|
|
@@ -29505,7 +31642,7 @@ function applyUnaryElemwiseMaybeComplex(v, realFn, complexFn, name, nativeOpCode
|
|
|
29505
31642
|
tensorOps.realUnaryElemwise(nativeOpCode, n, v.data, nativeOut);
|
|
29506
31643
|
let firstNaN = -1;
|
|
29507
31644
|
for (let i = 0; i < n; i++) {
|
|
29508
|
-
if (Number.isNaN(nativeOut[i])) {
|
|
31645
|
+
if (Number.isNaN(nativeOut[i]) && !Number.isNaN(v.data[i])) {
|
|
29509
31646
|
firstNaN = i;
|
|
29510
31647
|
break;
|
|
29511
31648
|
}
|
|
@@ -29517,7 +31654,7 @@ function applyUnaryElemwiseMaybeComplex(v, realFn, complexFn, name, nativeOpCode
|
|
|
29517
31654
|
const outI3 = allocFloat64Array(n);
|
|
29518
31655
|
let hasImag2 = false;
|
|
29519
31656
|
for (let i = 0; i < n; i++) {
|
|
29520
|
-
if (!Number.isNaN(nativeOut[i])) {
|
|
31657
|
+
if (!Number.isNaN(nativeOut[i]) || Number.isNaN(v.data[i])) {
|
|
29521
31658
|
outR3[i] = nativeOut[i];
|
|
29522
31659
|
} else {
|
|
29523
31660
|
const c = complexFn(v.data[i], 0);
|
|
@@ -29533,7 +31670,7 @@ function applyUnaryElemwiseMaybeComplex(v, realFn, complexFn, name, nativeOpCode
|
|
|
29533
31670
|
let hasImag = false;
|
|
29534
31671
|
for (let i = 0; i < n; i++) {
|
|
29535
31672
|
const r = realFn(v.data[i]);
|
|
29536
|
-
if (!Number.isNaN(r)) {
|
|
31673
|
+
if (!Number.isNaN(r) || Number.isNaN(v.data[i])) {
|
|
29537
31674
|
outR2[i] = r;
|
|
29538
31675
|
outI2[i] = 0;
|
|
29539
31676
|
} else {
|
|
@@ -34326,7 +36463,11 @@ function binop(op, a, b) {
|
|
|
34326
36463
|
result = mElemDiv(mb, ma);
|
|
34327
36464
|
break;
|
|
34328
36465
|
}
|
|
34329
|
-
|
|
36466
|
+
if (isRuntimeSparseMatrix(ma)) {
|
|
36467
|
+
result = mLeftDiv(ma, mb);
|
|
36468
|
+
break;
|
|
36469
|
+
}
|
|
36470
|
+
const tensorA = ma;
|
|
34330
36471
|
const tensorB = isRuntimeNumber(mb) ? RTV.tensor(allocFloat64Array([mb]), [1, 1]) : isRuntimeSparseMatrix(mb) ? sparseToDense(mb) : mb;
|
|
34331
36472
|
if (!isRuntimeTensor(tensorA) || !isRuntimeTensor(tensorB))
|
|
34332
36473
|
throw new RuntimeError(
|
|
@@ -38237,6 +40378,709 @@ function tryDatetimeDurationBinop(opName, a, b) {
|
|
|
38237
40378
|
);
|
|
38238
40379
|
}
|
|
38239
40380
|
|
|
40381
|
+
// src/numbl-core/helpers/prng.ts
|
|
40382
|
+
var _rngState = null;
|
|
40383
|
+
var _rngSeed = 0;
|
|
40384
|
+
var _bmSpare = null;
|
|
40385
|
+
function setRngShuffle() {
|
|
40386
|
+
_rngState = null;
|
|
40387
|
+
_rngSeed = 0;
|
|
40388
|
+
_bmSpare = null;
|
|
40389
|
+
}
|
|
40390
|
+
function setRngSeed(seed) {
|
|
40391
|
+
_rngSeed = seed;
|
|
40392
|
+
}
|
|
40393
|
+
function splitmix32(seed) {
|
|
40394
|
+
let s = seed | 0;
|
|
40395
|
+
return () => {
|
|
40396
|
+
s = s + 2654435769 | 0;
|
|
40397
|
+
let z = s;
|
|
40398
|
+
z = Math.imul(z ^ z >>> 16, 2246822507);
|
|
40399
|
+
z = Math.imul(z ^ z >>> 13, 3266489909);
|
|
40400
|
+
return (z ^ z >>> 16) >>> 0;
|
|
40401
|
+
};
|
|
40402
|
+
}
|
|
40403
|
+
function seedRng(seed) {
|
|
40404
|
+
_bmSpare = null;
|
|
40405
|
+
const sm = splitmix32(seed);
|
|
40406
|
+
_rngState = new Uint32Array([sm(), sm(), sm(), sm()]);
|
|
40407
|
+
if (_rngState[0] === 0 && _rngState[1] === 0 && _rngState[2] === 0 && _rngState[3] === 0) {
|
|
40408
|
+
_rngState[0] = 1;
|
|
40409
|
+
}
|
|
40410
|
+
}
|
|
40411
|
+
function xoshiro128ss() {
|
|
40412
|
+
const s = _rngState;
|
|
40413
|
+
const result = Math.imul(rotl(Math.imul(s[1], 5), 7), 9) >>> 0;
|
|
40414
|
+
const t = s[1] << 9;
|
|
40415
|
+
s[2] ^= s[0];
|
|
40416
|
+
s[3] ^= s[1];
|
|
40417
|
+
s[1] ^= s[2];
|
|
40418
|
+
s[0] ^= s[3];
|
|
40419
|
+
s[2] ^= t;
|
|
40420
|
+
s[3] = rotl(s[3], 11);
|
|
40421
|
+
return result;
|
|
40422
|
+
}
|
|
40423
|
+
function rotl(x, k) {
|
|
40424
|
+
return (x << k | x >>> 32 - k) >>> 0;
|
|
40425
|
+
}
|
|
40426
|
+
function rngRandom() {
|
|
40427
|
+
if (_rngState === null) return Math.random();
|
|
40428
|
+
return (xoshiro128ss() >>> 0) / 4294967296;
|
|
40429
|
+
}
|
|
40430
|
+
function boxMullerRandom() {
|
|
40431
|
+
if (_bmSpare !== null) {
|
|
40432
|
+
const s2 = _bmSpare;
|
|
40433
|
+
_bmSpare = null;
|
|
40434
|
+
return s2;
|
|
40435
|
+
}
|
|
40436
|
+
let u, v, s;
|
|
40437
|
+
do {
|
|
40438
|
+
u = 2 * rngRandom() - 1;
|
|
40439
|
+
v = 2 * rngRandom() - 1;
|
|
40440
|
+
s = u * u + v * v;
|
|
40441
|
+
} while (s >= 1 || s === 0);
|
|
40442
|
+
const mul = Math.sqrt(-2 * Math.log(s) / s);
|
|
40443
|
+
_bmSpare = v * mul;
|
|
40444
|
+
return u * mul;
|
|
40445
|
+
}
|
|
40446
|
+
function fillRandn(data) {
|
|
40447
|
+
if (_rngState !== null) {
|
|
40448
|
+
const bridge = getLapackBridge();
|
|
40449
|
+
if (bridge?.fillRandn) {
|
|
40450
|
+
const r = bridge.fillRandn(
|
|
40451
|
+
_rngState,
|
|
40452
|
+
data.length,
|
|
40453
|
+
_bmSpare ?? 0,
|
|
40454
|
+
_bmSpare !== null
|
|
40455
|
+
);
|
|
40456
|
+
_bmSpare = r.hasSpare ? r.spare : null;
|
|
40457
|
+
data.set(r.data);
|
|
40458
|
+
return;
|
|
40459
|
+
}
|
|
40460
|
+
}
|
|
40461
|
+
const n = data.length;
|
|
40462
|
+
let i = 0;
|
|
40463
|
+
if (_bmSpare !== null && i < n) {
|
|
40464
|
+
data[i++] = _bmSpare;
|
|
40465
|
+
_bmSpare = null;
|
|
40466
|
+
}
|
|
40467
|
+
for (; i + 1 < n; i += 2) {
|
|
40468
|
+
let u, v, s;
|
|
40469
|
+
do {
|
|
40470
|
+
u = 2 * rngRandom() - 1;
|
|
40471
|
+
v = 2 * rngRandom() - 1;
|
|
40472
|
+
s = u * u + v * v;
|
|
40473
|
+
} while (s >= 1 || s === 0);
|
|
40474
|
+
const mul = Math.sqrt(-2 * Math.log(s) / s);
|
|
40475
|
+
data[i] = u * mul;
|
|
40476
|
+
data[i + 1] = v * mul;
|
|
40477
|
+
}
|
|
40478
|
+
if (i < n) {
|
|
40479
|
+
data[i] = boxMullerRandom();
|
|
40480
|
+
}
|
|
40481
|
+
}
|
|
40482
|
+
function getRngStateStruct() {
|
|
40483
|
+
const stateArray = _rngState ? RTV.tensor(allocFloat64Array(Array.from(_rngState).map((v) => v)), [4, 1]) : RTV.tensor(allocFloat64Array(0), [0, 1]);
|
|
40484
|
+
return RTV.struct({
|
|
40485
|
+
Type: RTV.char("twister"),
|
|
40486
|
+
Seed: RTV.num(_rngSeed),
|
|
40487
|
+
State: stateArray
|
|
40488
|
+
});
|
|
40489
|
+
}
|
|
40490
|
+
function restoreRngState(s) {
|
|
40491
|
+
const seedField = s.fields.get("Seed");
|
|
40492
|
+
const stateField = s.fields.get("State");
|
|
40493
|
+
if (seedField === void 0 || stateField === void 0) {
|
|
40494
|
+
throw new RuntimeError("rng: invalid state structure");
|
|
40495
|
+
}
|
|
40496
|
+
_rngSeed = Math.round(toNumber(seedField));
|
|
40497
|
+
if (isRuntimeTensor(stateField) && stateField.data.length === 4) {
|
|
40498
|
+
_rngState = new Uint32Array(4);
|
|
40499
|
+
for (let i = 0; i < 4; i++) _rngState[i] = stateField.data[i] >>> 0;
|
|
40500
|
+
} else {
|
|
40501
|
+
_rngState = null;
|
|
40502
|
+
}
|
|
40503
|
+
}
|
|
40504
|
+
|
|
40505
|
+
// src/numbl-core/interpreter/builtins/sparse-solvers.ts
|
|
40506
|
+
function toSparseArg(v, name) {
|
|
40507
|
+
if (isRuntimeSparseMatrix(v)) return v;
|
|
40508
|
+
if (isRuntimeTensor(v)) return denseToSparse(v);
|
|
40509
|
+
if (isRuntimeNumber(v))
|
|
40510
|
+
return denseToSparse(RTV.tensor(allocFloat64Array([v]), [1, 1]));
|
|
40511
|
+
if (isRuntimeLogical(v))
|
|
40512
|
+
return denseToSparse(RTV.tensor(allocFloat64Array([v ? 1 : 0]), [1, 1]));
|
|
40513
|
+
throw new RuntimeError(`${name}: argument must be a numeric matrix`);
|
|
40514
|
+
}
|
|
40515
|
+
var ROW_VECTOR = { kind: "tensor", isComplex: false };
|
|
40516
|
+
registerIBuiltin({
|
|
40517
|
+
name: "symrcm",
|
|
40518
|
+
help: {
|
|
40519
|
+
signatures: ["p = symrcm(A)"],
|
|
40520
|
+
description: "Reverse Cuthill-McKee ordering of the pattern of A + A'. A(p,p) tends to have a smaller bandwidth than A."
|
|
40521
|
+
},
|
|
40522
|
+
resolve: (argTypes, nargout) => {
|
|
40523
|
+
if (argTypes.length !== 1 || nargout > 1) return null;
|
|
40524
|
+
return {
|
|
40525
|
+
outputTypes: [ROW_VECTOR],
|
|
40526
|
+
apply: (args) => permVectorTensor(reverseCuthillMcKee(toSparseArg(args[0], "symrcm")))
|
|
40527
|
+
};
|
|
40528
|
+
}
|
|
40529
|
+
});
|
|
40530
|
+
registerIBuiltin({
|
|
40531
|
+
name: "amd",
|
|
40532
|
+
help: {
|
|
40533
|
+
signatures: ["p = amd(A)"],
|
|
40534
|
+
description: "Minimum degree ordering of the pattern of A + A'. chol(A(p,p)) tends to be sparser than chol(A). numbl uses an exact minimum degree ordering, so p can differ from MATLAB's approximate minimum degree permutation."
|
|
40535
|
+
},
|
|
40536
|
+
resolve: (argTypes, nargout) => {
|
|
40537
|
+
if (argTypes.length < 1 || argTypes.length > 2 || nargout > 1) return null;
|
|
40538
|
+
return {
|
|
40539
|
+
outputTypes: [ROW_VECTOR],
|
|
40540
|
+
apply: (args) => permVectorTensor(minimumDegreeOrdering(toSparseArg(args[0], "amd")))
|
|
40541
|
+
};
|
|
40542
|
+
}
|
|
40543
|
+
});
|
|
40544
|
+
registerIBuiltin({
|
|
40545
|
+
name: "colamd",
|
|
40546
|
+
help: {
|
|
40547
|
+
signatures: ["p = colamd(A)"],
|
|
40548
|
+
description: "Column ordering for LU: minimum degree ordering of the pattern of A'*A. lu(A(:,p)) tends to produce sparser factors than lu(A)."
|
|
40549
|
+
},
|
|
40550
|
+
resolve: (argTypes, nargout) => {
|
|
40551
|
+
if (argTypes.length < 1 || argTypes.length > 2 || nargout > 1) return null;
|
|
40552
|
+
return {
|
|
40553
|
+
outputTypes: [ROW_VECTOR],
|
|
40554
|
+
apply: (args) => permVectorTensor(columnOrdering(toSparseArg(args[0], "colamd")))
|
|
40555
|
+
};
|
|
40556
|
+
}
|
|
40557
|
+
});
|
|
40558
|
+
function sampleDistinct(total, k) {
|
|
40559
|
+
if (k >= total) {
|
|
40560
|
+
const all2 = new Int32Array(total);
|
|
40561
|
+
for (let i = 0; i < total; i++) all2[i] = i;
|
|
40562
|
+
return all2;
|
|
40563
|
+
}
|
|
40564
|
+
let picked;
|
|
40565
|
+
if (k > total / 3) {
|
|
40566
|
+
const idx = new Int32Array(total);
|
|
40567
|
+
for (let i = 0; i < total; i++) idx[i] = i;
|
|
40568
|
+
for (let i = 0; i < k; i++) {
|
|
40569
|
+
const j = i + Math.floor(rngRandom() * (total - i));
|
|
40570
|
+
const t = idx[i];
|
|
40571
|
+
idx[i] = idx[j];
|
|
40572
|
+
idx[j] = t;
|
|
40573
|
+
}
|
|
40574
|
+
picked = idx.slice(0, k);
|
|
40575
|
+
} else {
|
|
40576
|
+
const set = /* @__PURE__ */ new Set();
|
|
40577
|
+
while (set.size < k) set.add(Math.floor(rngRandom() * total));
|
|
40578
|
+
picked = Int32Array.from(set);
|
|
40579
|
+
}
|
|
40580
|
+
return picked.sort();
|
|
40581
|
+
}
|
|
40582
|
+
function sparseFromLinearIndices(m, n, idx, gen) {
|
|
40583
|
+
const nnz = idx.length;
|
|
40584
|
+
const ir = new Int32Array(nnz);
|
|
40585
|
+
const jc = new Int32Array(n + 1);
|
|
40586
|
+
const pr = allocFloat64Array(nnz);
|
|
40587
|
+
for (let k = 0; k < nnz; k++) {
|
|
40588
|
+
const col = Math.floor(idx[k] / m);
|
|
40589
|
+
ir[k] = idx[k] - col * m;
|
|
40590
|
+
jc[col + 1]++;
|
|
40591
|
+
pr[k] = gen();
|
|
40592
|
+
}
|
|
40593
|
+
for (let c = 0; c < n; c++) jc[c + 1] += jc[c];
|
|
40594
|
+
return RTV.sparseMatrix(m, n, ir, jc, pr);
|
|
40595
|
+
}
|
|
40596
|
+
function registerSprand(name, gen) {
|
|
40597
|
+
registerIBuiltin({
|
|
40598
|
+
name,
|
|
40599
|
+
help: {
|
|
40600
|
+
signatures: [`R = ${name}(m, n, density)`, `R = ${name}(S)`],
|
|
40601
|
+
description: `Random m-by-n sparse matrix with approximately density*m*n ` + (name === "sprand" ? "uniformly" : "normally") + ` distributed nonzeros, or a matrix with the pattern of S and random values.`
|
|
40602
|
+
},
|
|
40603
|
+
resolve: (argTypes, nargout) => {
|
|
40604
|
+
if (nargout > 1) return null;
|
|
40605
|
+
if (argTypes.length !== 1 && argTypes.length < 3) return null;
|
|
40606
|
+
return {
|
|
40607
|
+
outputTypes: [{ kind: "sparse_matrix", isComplex: false }],
|
|
40608
|
+
apply: (args) => {
|
|
40609
|
+
if (args.length === 1) {
|
|
40610
|
+
const S = toSparseArg(args[0], name);
|
|
40611
|
+
const pr = allocFloat64Array(S.pr.length);
|
|
40612
|
+
for (let k2 = 0; k2 < pr.length; k2++) pr[k2] = gen();
|
|
40613
|
+
return RTV.sparseMatrix(
|
|
40614
|
+
S.m,
|
|
40615
|
+
S.n,
|
|
40616
|
+
new Int32Array(S.ir),
|
|
40617
|
+
new Int32Array(S.jc),
|
|
40618
|
+
pr
|
|
40619
|
+
);
|
|
40620
|
+
}
|
|
40621
|
+
if (args.length > 3)
|
|
40622
|
+
throw new RuntimeError(
|
|
40623
|
+
`${name}: the reciprocal-condition form ${name}(m, n, density, rc) is not supported`
|
|
40624
|
+
);
|
|
40625
|
+
const m = Math.round(toNumber(args[0]));
|
|
40626
|
+
const n = Math.round(toNumber(args[1]));
|
|
40627
|
+
const density = toNumber(args[2]);
|
|
40628
|
+
if (!(density >= 0 && density <= 1))
|
|
40629
|
+
throw new RuntimeError(`${name}: density must be in [0, 1]`);
|
|
40630
|
+
const total = m * n;
|
|
40631
|
+
const k = Math.min(total, Math.round(density * total));
|
|
40632
|
+
return sparseFromLinearIndices(m, n, sampleDistinct(total, k), gen);
|
|
40633
|
+
}
|
|
40634
|
+
};
|
|
40635
|
+
}
|
|
40636
|
+
});
|
|
40637
|
+
}
|
|
40638
|
+
registerSprand("sprand", rngRandom);
|
|
40639
|
+
registerSprand("sprandn", boxMullerRandom);
|
|
40640
|
+
registerIBuiltin({
|
|
40641
|
+
name: "sprandsym",
|
|
40642
|
+
help: {
|
|
40643
|
+
signatures: ["R = sprandsym(n, density)", "R = sprandsym(S)"],
|
|
40644
|
+
description: "Symmetric random n-by-n sparse matrix with approximately density*n*n normally distributed nonzeros, or a symmetric matrix with the pattern of the lower triangle of S."
|
|
40645
|
+
},
|
|
40646
|
+
resolve: (argTypes, nargout) => {
|
|
40647
|
+
if (nargout > 1 || argTypes.length < 1 || argTypes.length > 2) return null;
|
|
40648
|
+
return {
|
|
40649
|
+
outputTypes: [{ kind: "sparse_matrix", isComplex: false }],
|
|
40650
|
+
apply: (args) => {
|
|
40651
|
+
let n;
|
|
40652
|
+
let lowerIdx;
|
|
40653
|
+
if (args.length === 1) {
|
|
40654
|
+
const S = toSparseArg(args[0], "sprandsym");
|
|
40655
|
+
if (S.m !== S.n)
|
|
40656
|
+
throw new RuntimeError("sprandsym: S must be square");
|
|
40657
|
+
n = S.n;
|
|
40658
|
+
const idx = [];
|
|
40659
|
+
for (let j = 0; j < n; j++)
|
|
40660
|
+
for (let k = S.jc[j]; k < S.jc[j + 1]; k++)
|
|
40661
|
+
if (S.ir[k] >= j) idx.push(j * n + S.ir[k]);
|
|
40662
|
+
lowerIdx = Int32Array.from(idx);
|
|
40663
|
+
} else {
|
|
40664
|
+
n = Math.round(toNumber(args[0]));
|
|
40665
|
+
const density = toNumber(args[1]);
|
|
40666
|
+
if (!(density >= 0 && density <= 1))
|
|
40667
|
+
throw new RuntimeError("sprandsym: density must be in [0, 1]");
|
|
40668
|
+
const tri = n * (n + 1) / 2;
|
|
40669
|
+
const k = Math.min(tri, Math.round(density * n * n / 2));
|
|
40670
|
+
const triIdx = sampleDistinct(tri, k);
|
|
40671
|
+
const lin = [];
|
|
40672
|
+
for (let t = 0; t < triIdx.length; t++) {
|
|
40673
|
+
let r = triIdx[t];
|
|
40674
|
+
let col = 0;
|
|
40675
|
+
while (r >= n - col) {
|
|
40676
|
+
r -= n - col;
|
|
40677
|
+
col++;
|
|
40678
|
+
}
|
|
40679
|
+
lin.push(col * n + col + r);
|
|
40680
|
+
}
|
|
40681
|
+
lowerIdx = Int32Array.from(lin).sort();
|
|
40682
|
+
}
|
|
40683
|
+
const lower = sparseFromLinearIndices(n, n, lowerIdx, boxMullerRandom);
|
|
40684
|
+
const Lt = sparseTranspose(lower);
|
|
40685
|
+
const dense = sparseToDense(lower).data;
|
|
40686
|
+
const denseT = sparseToDense(Lt).data;
|
|
40687
|
+
for (let i = 0; i < dense.length; i++) dense[i] += denseT[i];
|
|
40688
|
+
for (let i = 0; i < n; i++) dense[i + i * n] /= 2;
|
|
40689
|
+
return denseDataToSparse(dense, n, n);
|
|
40690
|
+
}
|
|
40691
|
+
};
|
|
40692
|
+
}
|
|
40693
|
+
});
|
|
40694
|
+
var DEC_CLASS = "decomposition";
|
|
40695
|
+
function isDecomposition(v) {
|
|
40696
|
+
return isRuntimeClassInstance(v) && v.className === DEC_CLASS;
|
|
40697
|
+
}
|
|
40698
|
+
function permFromField(d, name) {
|
|
40699
|
+
const t = d.fields.get(name);
|
|
40700
|
+
if (t === void 0 || !isRuntimeTensor(t))
|
|
40701
|
+
throw new RuntimeError("decomposition: corrupt");
|
|
40702
|
+
const p2 = new Int32Array(t.data.length);
|
|
40703
|
+
for (let i = 0; i < p2.length; i++) p2[i] = t.data[i] - 1;
|
|
40704
|
+
return p2;
|
|
40705
|
+
}
|
|
40706
|
+
function sparseField(d, name) {
|
|
40707
|
+
const v = d.fields.get(name);
|
|
40708
|
+
if (v === void 0 || !isRuntimeSparseMatrix(v))
|
|
40709
|
+
throw new RuntimeError("decomposition: corrupt");
|
|
40710
|
+
return v;
|
|
40711
|
+
}
|
|
40712
|
+
function charField(d, name) {
|
|
40713
|
+
const v = d.fields.get(name);
|
|
40714
|
+
if (v === void 0) throw new RuntimeError("decomposition: corrupt");
|
|
40715
|
+
return parseStringArgLower(v);
|
|
40716
|
+
}
|
|
40717
|
+
function diagRatio(S) {
|
|
40718
|
+
let lo = Infinity;
|
|
40719
|
+
let hi = 0;
|
|
40720
|
+
for (let j = 0; j < S.n; j++) {
|
|
40721
|
+
let d = 0;
|
|
40722
|
+
for (let k = S.jc[j]; k < S.jc[j + 1]; k++)
|
|
40723
|
+
if (S.ir[k] === j) {
|
|
40724
|
+
d = Math.abs(S.pr[k]);
|
|
40725
|
+
break;
|
|
40726
|
+
}
|
|
40727
|
+
if (d < lo) lo = d;
|
|
40728
|
+
if (d > hi) hi = d;
|
|
40729
|
+
}
|
|
40730
|
+
if (S.n === 0) return 1;
|
|
40731
|
+
return hi === 0 ? 0 : lo / hi;
|
|
40732
|
+
}
|
|
40733
|
+
function denseLuFactors(data, n) {
|
|
40734
|
+
const bridge = getEffectiveBridge("lu", "lu");
|
|
40735
|
+
if (!bridge?.lu) throw new RuntimeError("decomposition: LU unavailable");
|
|
40736
|
+
const { LU, ipiv } = bridge.lu(toF64(data), n, n);
|
|
40737
|
+
const perm = new Int32Array(n);
|
|
40738
|
+
for (let i = 0; i < n; i++) perm[i] = i;
|
|
40739
|
+
for (let i = 0; i < ipiv.length; i++) {
|
|
40740
|
+
const j = ipiv[i] - 1;
|
|
40741
|
+
if (j !== i) {
|
|
40742
|
+
const t = perm[i];
|
|
40743
|
+
perm[i] = perm[j];
|
|
40744
|
+
perm[j] = t;
|
|
40745
|
+
}
|
|
40746
|
+
}
|
|
40747
|
+
const L = allocFloat64Array(n * n);
|
|
40748
|
+
const U = allocFloat64Array(n * n);
|
|
40749
|
+
let singular = false;
|
|
40750
|
+
for (let j = 0; j < n; j++) {
|
|
40751
|
+
L[j + j * n] = 1;
|
|
40752
|
+
for (let i = j + 1; i < n; i++) L[i + j * n] = LU[i + j * n];
|
|
40753
|
+
for (let i = 0; i <= j; i++) U[i + j * n] = LU[i + j * n];
|
|
40754
|
+
if (U[j + j * n] === 0) singular = true;
|
|
40755
|
+
}
|
|
40756
|
+
return {
|
|
40757
|
+
L: denseDataToSparse(L, n, n),
|
|
40758
|
+
U: denseDataToSparse(U, n, n),
|
|
40759
|
+
p: perm,
|
|
40760
|
+
q: identityPerm(n),
|
|
40761
|
+
singular
|
|
40762
|
+
};
|
|
40763
|
+
}
|
|
40764
|
+
function denseCholLower(data, n) {
|
|
40765
|
+
const bridge = getEffectiveBridge("chol", "chol");
|
|
40766
|
+
if (!bridge?.chol) throw new RuntimeError("decomposition: chol unavailable");
|
|
40767
|
+
const { R, info } = bridge.chol(toF64(data), n, false);
|
|
40768
|
+
if (info > 0) return null;
|
|
40769
|
+
return denseDataToSparse(R, n, n);
|
|
40770
|
+
}
|
|
40771
|
+
function denseIsTriangular(data, n, upper) {
|
|
40772
|
+
for (let j = 0; j < n; j++)
|
|
40773
|
+
for (let i = 0; i < n; i++) {
|
|
40774
|
+
if (upper ? i <= j : i >= j) continue;
|
|
40775
|
+
if (data[i + j * n] !== 0) return false;
|
|
40776
|
+
}
|
|
40777
|
+
return true;
|
|
40778
|
+
}
|
|
40779
|
+
registerIBuiltin({
|
|
40780
|
+
name: "decomposition",
|
|
40781
|
+
help: {
|
|
40782
|
+
signatures: [
|
|
40783
|
+
"dA = decomposition(A)",
|
|
40784
|
+
"dA = decomposition(A, type)",
|
|
40785
|
+
"dA = decomposition(A, 'triangular', 'upper' | 'lower')",
|
|
40786
|
+
"x = dA \\ b",
|
|
40787
|
+
"x = b / dA"
|
|
40788
|
+
],
|
|
40789
|
+
description: "Factor a square matrix once and reuse the factors: dA \\ b and b / dA solve with the stored factorization. type is 'auto' (default), 'chol', 'lu', or 'triangular'; other MATLAB types fall back to LU. Sparse matrices use the sparse Cholesky / LU with a fill-reducing ordering. Properties: MatrixSize, Type, Datatype, IsReal, IsConjugateTransposed, ScaleFactor, CheckCondition."
|
|
40790
|
+
},
|
|
40791
|
+
resolve: (argTypes, nargout) => {
|
|
40792
|
+
if (argTypes.length < 1 || nargout > 1) return null;
|
|
40793
|
+
return {
|
|
40794
|
+
outputTypes: [{ kind: "unknown" }],
|
|
40795
|
+
apply: (args) => buildDecomposition(args)
|
|
40796
|
+
};
|
|
40797
|
+
}
|
|
40798
|
+
});
|
|
40799
|
+
function buildDecomposition(args) {
|
|
40800
|
+
const A = args[0];
|
|
40801
|
+
let type = "auto";
|
|
40802
|
+
let triangle = null;
|
|
40803
|
+
let checkCondition = true;
|
|
40804
|
+
let luTol = 1;
|
|
40805
|
+
let i = 1;
|
|
40806
|
+
const isStr = (v) => isRuntimeChar(v) || isRuntimeString(v);
|
|
40807
|
+
while (i < args.length) {
|
|
40808
|
+
const a = args[i];
|
|
40809
|
+
if (!isStr(a))
|
|
40810
|
+
throw new RuntimeError("decomposition: options must be strings");
|
|
40811
|
+
const s = parseStringArgLower(a);
|
|
40812
|
+
if (s === "upper" || s === "lower") {
|
|
40813
|
+
triangle = s;
|
|
40814
|
+
i++;
|
|
40815
|
+
continue;
|
|
40816
|
+
}
|
|
40817
|
+
if (s === "checkcondition" || s === "ranktolerance" || s === "banddensity" || s === "ldlpivottolerance" || s === "lupivottolerance") {
|
|
40818
|
+
if (i + 1 >= args.length)
|
|
40819
|
+
throw new RuntimeError(`decomposition: missing value for '${s}'`);
|
|
40820
|
+
const v = args[i + 1];
|
|
40821
|
+
if (s === "checkcondition") checkCondition = toNumber(v) !== 0;
|
|
40822
|
+
if (s === "lupivottolerance") luTol = toNumber(v);
|
|
40823
|
+
i += 2;
|
|
40824
|
+
continue;
|
|
40825
|
+
}
|
|
40826
|
+
if (i === 1) {
|
|
40827
|
+
type = s;
|
|
40828
|
+
i++;
|
|
40829
|
+
continue;
|
|
40830
|
+
}
|
|
40831
|
+
throw new RuntimeError(`decomposition: unknown option '${s}'`);
|
|
40832
|
+
}
|
|
40833
|
+
const known = [
|
|
40834
|
+
"auto",
|
|
40835
|
+
"chol",
|
|
40836
|
+
"lu",
|
|
40837
|
+
"triangular",
|
|
40838
|
+
"ldl",
|
|
40839
|
+
"qr",
|
|
40840
|
+
"banded",
|
|
40841
|
+
"diagonal",
|
|
40842
|
+
"permutedtriangular",
|
|
40843
|
+
"hessenberg",
|
|
40844
|
+
"cod"
|
|
40845
|
+
];
|
|
40846
|
+
if (!known.includes(type))
|
|
40847
|
+
throw new RuntimeError(
|
|
40848
|
+
`decomposition: unknown decomposition type '${type}'`
|
|
40849
|
+
);
|
|
40850
|
+
let S = null;
|
|
40851
|
+
let dense = null;
|
|
40852
|
+
let n;
|
|
40853
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
40854
|
+
if (A.pi)
|
|
40855
|
+
throw new RuntimeError(
|
|
40856
|
+
"decomposition: complex matrices are not supported"
|
|
40857
|
+
);
|
|
40858
|
+
if (A.m !== A.n)
|
|
40859
|
+
throw new RuntimeError(
|
|
40860
|
+
"decomposition: only square matrices are supported"
|
|
40861
|
+
);
|
|
40862
|
+
S = A;
|
|
40863
|
+
n = A.n;
|
|
40864
|
+
} else if (isRuntimeTensor(A) || isRuntimeNumber(A)) {
|
|
40865
|
+
const t = isRuntimeNumber(A) ? RTV.tensor(allocFloat64Array([A]), [1, 1]) : A;
|
|
40866
|
+
if (t.imag)
|
|
40867
|
+
throw new RuntimeError(
|
|
40868
|
+
"decomposition: complex matrices are not supported"
|
|
40869
|
+
);
|
|
40870
|
+
const [m, nn] = tensorSize2D(t);
|
|
40871
|
+
if (m !== nn)
|
|
40872
|
+
throw new RuntimeError(
|
|
40873
|
+
"decomposition: only square matrices are supported"
|
|
40874
|
+
);
|
|
40875
|
+
n = nn;
|
|
40876
|
+
dense = t.data;
|
|
40877
|
+
} else {
|
|
40878
|
+
throw new RuntimeError("decomposition: A must be a numeric matrix");
|
|
40879
|
+
}
|
|
40880
|
+
const fields = /* @__PURE__ */ new Map();
|
|
40881
|
+
const setCommon = (typeName, rc) => {
|
|
40882
|
+
fields.set("MatrixSize", RTV.tensor(allocFloat64Array([n, n]), [1, 2]));
|
|
40883
|
+
fields.set("Type", RTV.char(typeName));
|
|
40884
|
+
fields.set("Datatype", RTV.char("double"));
|
|
40885
|
+
fields.set("IsReal", RTV.logical(true));
|
|
40886
|
+
fields.set("IsConjugateTransposed", RTV.logical(false));
|
|
40887
|
+
fields.set("ScaleFactor", RTV.num(1));
|
|
40888
|
+
fields.set("CheckCondition", RTV.logical(checkCondition));
|
|
40889
|
+
fields.set("_rcond", RTV.num(rc));
|
|
40890
|
+
};
|
|
40891
|
+
const storeTriangular = (T, upper) => {
|
|
40892
|
+
fields.set("_kind", RTV.char("triangular"));
|
|
40893
|
+
fields.set("_T", T);
|
|
40894
|
+
fields.set("_upper", RTV.logical(upper));
|
|
40895
|
+
setCommon("triangular", diagRatio(T));
|
|
40896
|
+
};
|
|
40897
|
+
const storeChol = (L, p2) => {
|
|
40898
|
+
fields.set("_kind", RTV.char("chol"));
|
|
40899
|
+
fields.set("_L", L);
|
|
40900
|
+
fields.set("_Lt", sparseTranspose(L));
|
|
40901
|
+
fields.set("_p", permVectorTensor(p2));
|
|
40902
|
+
setCommon("chol", diagRatio(L) ** 2);
|
|
40903
|
+
};
|
|
40904
|
+
const storeLu = (lu3) => {
|
|
40905
|
+
fields.set("_kind", RTV.char("lu"));
|
|
40906
|
+
fields.set("_L", lu3.L);
|
|
40907
|
+
fields.set("_U", lu3.U);
|
|
40908
|
+
fields.set("_p", permVectorTensor(lu3.p));
|
|
40909
|
+
fields.set("_q", permVectorTensor(lu3.q));
|
|
40910
|
+
setCommon(type === "auto" || type === "lu" ? "lu" : type, diagRatio(lu3.U));
|
|
40911
|
+
};
|
|
40912
|
+
const upperOk = S ? sparseIsUpper(S) : denseIsTriangular(dense, n, true);
|
|
40913
|
+
const lowerOk = S ? sparseIsLower(S) : denseIsTriangular(dense, n, false);
|
|
40914
|
+
if (type === "triangular" || type === "auto" && (upperOk || lowerOk)) {
|
|
40915
|
+
let upper;
|
|
40916
|
+
if (triangle) upper = triangle === "upper";
|
|
40917
|
+
else if (upperOk) upper = true;
|
|
40918
|
+
else if (lowerOk) upper = false;
|
|
40919
|
+
else throw new RuntimeError("decomposition: matrix is not triangular");
|
|
40920
|
+
const T = S ?? denseDataToSparse(dense, n, n);
|
|
40921
|
+
storeTriangular(T, upper);
|
|
40922
|
+
return new RuntimeClassInstance(DEC_CLASS, fields, false);
|
|
40923
|
+
}
|
|
40924
|
+
const symmetric = S !== null && sparseIsSymmetric(S);
|
|
40925
|
+
if (type === "chol" || type === "auto" && symmetric) {
|
|
40926
|
+
if (S) {
|
|
40927
|
+
const perm = minimumDegreeOrdering(S);
|
|
40928
|
+
const res = sparseChol(sparsePermute(S, perm, perm));
|
|
40929
|
+
if (res.ok) {
|
|
40930
|
+
storeChol(res.L, perm);
|
|
40931
|
+
return new RuntimeClassInstance(DEC_CLASS, fields, false);
|
|
40932
|
+
}
|
|
40933
|
+
} else {
|
|
40934
|
+
const L = denseCholLower(dense, n);
|
|
40935
|
+
if (L) {
|
|
40936
|
+
storeChol(L, identityPerm(n));
|
|
40937
|
+
return new RuntimeClassInstance(DEC_CLASS, fields, false);
|
|
40938
|
+
}
|
|
40939
|
+
}
|
|
40940
|
+
if (type === "chol")
|
|
40941
|
+
throw new RuntimeError(
|
|
40942
|
+
"Cholesky decomposition requires the input matrix to be positive definite."
|
|
40943
|
+
);
|
|
40944
|
+
}
|
|
40945
|
+
const lu2 = S ? sparseLu(S, columnOrdering(S), luTol) : denseLuFactors(dense, n);
|
|
40946
|
+
if (lu2.singular) emitWarning(SINGULAR_WARNING);
|
|
40947
|
+
storeLu(lu2);
|
|
40948
|
+
return new RuntimeClassInstance(DEC_CLASS, fields, false);
|
|
40949
|
+
}
|
|
40950
|
+
function decompositionRcond(d) {
|
|
40951
|
+
const rc = d.fields.get("_rcond");
|
|
40952
|
+
return typeof rc === "number" ? rc : 1;
|
|
40953
|
+
}
|
|
40954
|
+
registerIBuiltin({
|
|
40955
|
+
name: "isIllConditioned",
|
|
40956
|
+
help: {
|
|
40957
|
+
signatures: ["tf = isIllConditioned(dA)"],
|
|
40958
|
+
description: "True if the matrix stored in a decomposition object is ill conditioned (reciprocal condition estimate below eps)."
|
|
40959
|
+
},
|
|
40960
|
+
resolve: (argTypes, nargout) => {
|
|
40961
|
+
if (argTypes.length !== 1 || nargout > 1) return null;
|
|
40962
|
+
return {
|
|
40963
|
+
outputTypes: [{ kind: "boolean" }],
|
|
40964
|
+
apply: (args) => {
|
|
40965
|
+
if (!isDecomposition(args[0]))
|
|
40966
|
+
throw new RuntimeError(
|
|
40967
|
+
"isIllConditioned: argument must be a decomposition object"
|
|
40968
|
+
);
|
|
40969
|
+
return RTV.logical(decompositionRcond(args[0]) < Number.EPSILON);
|
|
40970
|
+
}
|
|
40971
|
+
};
|
|
40972
|
+
}
|
|
40973
|
+
});
|
|
40974
|
+
function decompositionSolve(d, B, n, nrhs, transposed) {
|
|
40975
|
+
if (d.fields.get("CheckCondition") === true) {
|
|
40976
|
+
const rc = decompositionRcond(d);
|
|
40977
|
+
if (rc < Number.EPSILON)
|
|
40978
|
+
emitWarning(
|
|
40979
|
+
`Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND = ${rc.toExponential(6)}.`
|
|
40980
|
+
);
|
|
40981
|
+
}
|
|
40982
|
+
const kind = charField(d, "_kind");
|
|
40983
|
+
if (kind === "triangular") {
|
|
40984
|
+
let T = sparseField(d, "_T");
|
|
40985
|
+
let upper = d.fields.get("_upper") === true;
|
|
40986
|
+
if (transposed) {
|
|
40987
|
+
T = sparseTranspose(T);
|
|
40988
|
+
upper = !upper;
|
|
40989
|
+
}
|
|
40990
|
+
const r = upper ? sparseSolveUpper(T, B, nrhs) : sparseSolveLower(T, B, nrhs);
|
|
40991
|
+
if (r.singular) emitWarning(SINGULAR_WARNING);
|
|
40992
|
+
return r.x;
|
|
40993
|
+
}
|
|
40994
|
+
if (kind === "chol") {
|
|
40995
|
+
const L = sparseField(d, "_L");
|
|
40996
|
+
const p2 = permFromField(d, "_p");
|
|
40997
|
+
const bp = allocFloat64Array(B.length);
|
|
40998
|
+
for (let c = 0; c < nrhs; c++)
|
|
40999
|
+
for (let k = 0; k < n; k++) bp[c * n + k] = B[c * n + p2[k]];
|
|
41000
|
+
const y = sparseSolveLower(L, bp, nrhs).x;
|
|
41001
|
+
const z = sparseSolveUpper(sparseField(d, "_Lt"), y, nrhs).x;
|
|
41002
|
+
const x = allocFloat64Array(B.length);
|
|
41003
|
+
for (let c = 0; c < nrhs; c++)
|
|
41004
|
+
for (let k = 0; k < n; k++) x[c * n + p2[k]] = z[c * n + k];
|
|
41005
|
+
return x;
|
|
41006
|
+
}
|
|
41007
|
+
const lu2 = {
|
|
41008
|
+
L: sparseField(d, "_L"),
|
|
41009
|
+
U: sparseField(d, "_U"),
|
|
41010
|
+
p: permFromField(d, "_p"),
|
|
41011
|
+
q: permFromField(d, "_q"),
|
|
41012
|
+
singular: false
|
|
41013
|
+
};
|
|
41014
|
+
return transposed ? luSolveTransposed(lu2, B, nrhs) : luSolve(lu2, B, nrhs);
|
|
41015
|
+
}
|
|
41016
|
+
function rhsData(v) {
|
|
41017
|
+
if (isRuntimeSparseMatrix(v)) {
|
|
41018
|
+
if (v.pi)
|
|
41019
|
+
throw new RuntimeError(
|
|
41020
|
+
"decomposition: complex operands are not supported"
|
|
41021
|
+
);
|
|
41022
|
+
return { data: sparseToDense(v).data, m: v.m, n: v.n };
|
|
41023
|
+
}
|
|
41024
|
+
if (isRuntimeTensor(v)) {
|
|
41025
|
+
if (v.imag)
|
|
41026
|
+
throw new RuntimeError(
|
|
41027
|
+
"decomposition: complex operands are not supported"
|
|
41028
|
+
);
|
|
41029
|
+
const [m, n] = tensorSize2D(v);
|
|
41030
|
+
return { data: v.data, m, n };
|
|
41031
|
+
}
|
|
41032
|
+
if (isRuntimeNumber(v) || isRuntimeLogical(v))
|
|
41033
|
+
return { data: allocFloat64Array([toNumber(v)]), m: 1, n: 1 };
|
|
41034
|
+
throw new RuntimeError("decomposition: operand must be numeric");
|
|
41035
|
+
}
|
|
41036
|
+
function tryDecompositionDivide(name, a, b) {
|
|
41037
|
+
if (name === "mldivide") {
|
|
41038
|
+
if (!isDecomposition(a)) {
|
|
41039
|
+
if (isDecomposition(b))
|
|
41040
|
+
throw new RuntimeError(
|
|
41041
|
+
"decomposition: a decomposition object can only be the left operand of \\"
|
|
41042
|
+
);
|
|
41043
|
+
return void 0;
|
|
41044
|
+
}
|
|
41045
|
+
const n2 = toNumber(permSize(a));
|
|
41046
|
+
const rhs2 = rhsData(b);
|
|
41047
|
+
if (rhs2.m !== n2)
|
|
41048
|
+
throw new RuntimeError(
|
|
41049
|
+
`mldivide (\\): A is ${n2}\xD7${n2} but B has ${rhs2.m} rows`
|
|
41050
|
+
);
|
|
41051
|
+
const x2 = decompositionSolve(a, rhs2.data, n2, rhs2.n, false);
|
|
41052
|
+
return RTV.tensor(x2, [n2, rhs2.n]);
|
|
41053
|
+
}
|
|
41054
|
+
if (!isDecomposition(b)) {
|
|
41055
|
+
if (isDecomposition(a))
|
|
41056
|
+
throw new RuntimeError(
|
|
41057
|
+
"decomposition: a decomposition object can only be the right operand of /"
|
|
41058
|
+
);
|
|
41059
|
+
return void 0;
|
|
41060
|
+
}
|
|
41061
|
+
const n = toNumber(permSize(b));
|
|
41062
|
+
const rhs = rhsData(a);
|
|
41063
|
+
if (rhs.n !== n)
|
|
41064
|
+
throw new RuntimeError(
|
|
41065
|
+
`mrdivide (/): A is ${n}\xD7${n} but B has ${rhs.n} columns`
|
|
41066
|
+
);
|
|
41067
|
+
const nrhs = rhs.m;
|
|
41068
|
+
const Bt = allocFloat64Array(n * nrhs);
|
|
41069
|
+
for (let c = 0; c < nrhs; c++)
|
|
41070
|
+
for (let k = 0; k < n; k++) Bt[c * n + k] = rhs.data[c + k * nrhs];
|
|
41071
|
+
const xt = decompositionSolve(b, Bt, n, nrhs, true);
|
|
41072
|
+
const x = allocFloat64Array(n * nrhs);
|
|
41073
|
+
for (let c = 0; c < nrhs; c++)
|
|
41074
|
+
for (let k = 0; k < n; k++) x[c + k * nrhs] = xt[c * n + k];
|
|
41075
|
+
return RTV.tensor(x, [nrhs, n]);
|
|
41076
|
+
}
|
|
41077
|
+
function permSize(d) {
|
|
41078
|
+
const ms = d.fields.get("MatrixSize");
|
|
41079
|
+
if (ms === void 0 || !isRuntimeTensor(ms))
|
|
41080
|
+
throw new RuntimeError("decomposition: corrupt");
|
|
41081
|
+
return ms.data[0];
|
|
41082
|
+
}
|
|
41083
|
+
|
|
38240
41084
|
// src/numbl-core/interpreter/builtins/array-construction.ts
|
|
38241
41085
|
function isClassNameType(t) {
|
|
38242
41086
|
return t.kind === "char" || t.kind === "string";
|
|
@@ -38812,6 +41656,10 @@ for (const [name, op] of opMap) {
|
|
|
38812
41656
|
apply: (args) => {
|
|
38813
41657
|
const dt = tryDatetimeDurationBinop(name, args[0], args[1]);
|
|
38814
41658
|
if (dt !== void 0) return dt;
|
|
41659
|
+
if (name === "mldivide" || name === "mrdivide") {
|
|
41660
|
+
const dec = tryDecompositionDivide(name, args[0], args[1]);
|
|
41661
|
+
if (dec !== void 0) return dec;
|
|
41662
|
+
}
|
|
38815
41663
|
return op(args[0], args[1]);
|
|
38816
41664
|
}
|
|
38817
41665
|
};
|
|
@@ -39293,8 +42141,9 @@ defineBuiltin({
|
|
|
39293
42141
|
cases: [
|
|
39294
42142
|
{
|
|
39295
42143
|
match: (argTypes) => argTypes.length === 0 ? [{ kind: "number" }] : null,
|
|
39296
|
-
apply: () => {
|
|
42144
|
+
apply: (_args, nargout) => {
|
|
39297
42145
|
ticTime = performance.now();
|
|
42146
|
+
if (nargout === 0) return void 0;
|
|
39298
42147
|
return RTV.num(ticTime / 1e3);
|
|
39299
42148
|
}
|
|
39300
42149
|
}
|
|
@@ -40201,6 +43050,7 @@ function registerSpecialBuiltins(rt) {
|
|
|
40201
43050
|
if (na === 0) {
|
|
40202
43051
|
rt.output(`Elapsed time is ${elapsed.toFixed(6)} seconds.
|
|
40203
43052
|
`);
|
|
43053
|
+
return void 0;
|
|
40204
43054
|
}
|
|
40205
43055
|
return RTV.num(elapsed);
|
|
40206
43056
|
}
|
|
@@ -44286,6 +47136,7 @@ var Runtime = class _Runtime {
|
|
|
44286
47136
|
if (options.cancelSAB) {
|
|
44287
47137
|
this.cancelFlag = new Int32Array(options.cancelSAB);
|
|
44288
47138
|
}
|
|
47139
|
+
setWarningSink((msg) => this.output("Warning: " + msg + "\n"));
|
|
44289
47140
|
this.initBuiltins();
|
|
44290
47141
|
}
|
|
44291
47142
|
outputLines = [];
|
|
@@ -51461,6 +54312,24 @@ defineBuiltin({
|
|
|
51461
54312
|
});
|
|
51462
54313
|
|
|
51463
54314
|
// src/numbl-core/interpreter/builtins/linear-algebra.ts
|
|
54315
|
+
var SPARSE_TYPE = { kind: "sparse_matrix", isComplex: false };
|
|
54316
|
+
function toSparseOperand(v, name) {
|
|
54317
|
+
if (isRuntimeSparseMatrix(v)) return v;
|
|
54318
|
+
if (isRuntimeNumber(v) || typeof v === "boolean")
|
|
54319
|
+
return denseToSparse(RTV.tensor(allocFloat64Array([Number(v)]), [1, 1]));
|
|
54320
|
+
if (isRuntimeTensor(v)) return denseToSparse(v);
|
|
54321
|
+
throw new RuntimeError(`${name}: arguments must be numeric`);
|
|
54322
|
+
}
|
|
54323
|
+
function speyeSparse(n) {
|
|
54324
|
+
const ir = new Int32Array(n);
|
|
54325
|
+
const jc = new Int32Array(n + 1);
|
|
54326
|
+
const pr = allocFloat64Array(n).fill(1);
|
|
54327
|
+
for (let i = 0; i < n; i++) {
|
|
54328
|
+
ir[i] = i;
|
|
54329
|
+
jc[i + 1] = i + 1;
|
|
54330
|
+
}
|
|
54331
|
+
return RTV.sparseMatrix(n, n, ir, jc, pr);
|
|
54332
|
+
}
|
|
51464
54333
|
function isNumericJitType(t) {
|
|
51465
54334
|
return t.kind === "number" || t.kind === "boolean" || t.kind === "complex_or_number" || t.kind === "tensor" || t.kind === "sparse_matrix";
|
|
51466
54335
|
}
|
|
@@ -51501,12 +54370,53 @@ function normApply(args) {
|
|
|
51501
54370
|
const v = args[0];
|
|
51502
54371
|
if (isRuntimeNumber(v)) return RTV.num(Math.abs(v));
|
|
51503
54372
|
if (isRuntimeComplexNumber(v)) return RTV.num(Math.hypot(v.re, v.im));
|
|
51504
|
-
if (isRuntimeSparseMatrix(v))
|
|
54373
|
+
if (isRuntimeSparseMatrix(v)) {
|
|
54374
|
+
const fast = sparseNormFast(v, args[1]);
|
|
54375
|
+
if (fast !== null) return RTV.num(fast);
|
|
51505
54376
|
return normApply([sparseToDense(v), ...args.slice(1)]);
|
|
54377
|
+
}
|
|
51506
54378
|
if (!isRuntimeTensor(v))
|
|
51507
54379
|
throw new RuntimeError("norm: argument must be numeric");
|
|
51508
54380
|
return normImplTensor(v, args);
|
|
51509
54381
|
}
|
|
54382
|
+
function sparseNormFast(S, p2) {
|
|
54383
|
+
if (S.m === 1 || S.n === 1) return null;
|
|
54384
|
+
let kind = null;
|
|
54385
|
+
if (p2 === void 0) return null;
|
|
54386
|
+
if (isRuntimeNumber(p2)) {
|
|
54387
|
+
if (p2 === 1) kind = "one";
|
|
54388
|
+
else if (p2 === Infinity) kind = "inf";
|
|
54389
|
+
} else if (isRuntimeChar(p2) || isRuntimeString(p2)) {
|
|
54390
|
+
const s = parseStringArgLower(p2);
|
|
54391
|
+
if (s === "fro") kind = "fro";
|
|
54392
|
+
else if (s === "inf") kind = "inf";
|
|
54393
|
+
}
|
|
54394
|
+
if (kind === null) return null;
|
|
54395
|
+
const mag2 = (k) => S.pi ? Math.hypot(S.pr[k], S.pi[k]) : Math.abs(S.pr[k]);
|
|
54396
|
+
const nnz = S.jc[S.n];
|
|
54397
|
+
if (kind === "fro") {
|
|
54398
|
+
let sum2 = 0;
|
|
54399
|
+
for (let k = 0; k < nnz; k++) {
|
|
54400
|
+
const a = mag2(k);
|
|
54401
|
+
sum2 += a * a;
|
|
54402
|
+
}
|
|
54403
|
+
return Math.sqrt(sum2);
|
|
54404
|
+
}
|
|
54405
|
+
if (kind === "one") {
|
|
54406
|
+
let best2 = 0;
|
|
54407
|
+
for (let j = 0; j < S.n; j++) {
|
|
54408
|
+
let sum2 = 0;
|
|
54409
|
+
for (let k = S.jc[j]; k < S.jc[j + 1]; k++) sum2 += mag2(k);
|
|
54410
|
+
if (sum2 > best2) best2 = sum2;
|
|
54411
|
+
}
|
|
54412
|
+
return best2;
|
|
54413
|
+
}
|
|
54414
|
+
const rowSums = allocFloat64Array(S.m);
|
|
54415
|
+
for (let k = 0; k < nnz; k++) rowSums[S.ir[k]] += mag2(k);
|
|
54416
|
+
let best = 0;
|
|
54417
|
+
for (let i = 0; i < S.m; i++) if (rowSums[i] > best) best = rowSums[i];
|
|
54418
|
+
return best;
|
|
54419
|
+
}
|
|
51510
54420
|
function scaledEuclid(magnitudes, count) {
|
|
51511
54421
|
let scale = 0;
|
|
51512
54422
|
let ssq = 1;
|
|
@@ -52131,11 +55041,18 @@ defineBuiltin({
|
|
|
52131
55041
|
if (a.kind === "complex_or_number") return [COMPLEX_OR_NUM];
|
|
52132
55042
|
if (a.kind === "tensor")
|
|
52133
55043
|
return [{ kind: "tensor", isComplex: a.isComplex }];
|
|
55044
|
+
if (a.kind === "sparse_matrix")
|
|
55045
|
+
return [{ kind: "sparse_matrix", isComplex: a.isComplex }];
|
|
52134
55046
|
return null;
|
|
52135
55047
|
},
|
|
52136
|
-
apply: (args)
|
|
55048
|
+
apply: function invApply(args) {
|
|
52137
55049
|
if (args.length < 1) throw new RuntimeError("inv requires 1 argument");
|
|
52138
55050
|
const A = args[0];
|
|
55051
|
+
if (isRuntimeSparseMatrix(A)) {
|
|
55052
|
+
if (!A.pi) return sparseInverse(A);
|
|
55053
|
+
const dense = invApply([sparseToDense(A)]);
|
|
55054
|
+
return isRuntimeTensor(dense) ? denseToSparse(dense) : dense;
|
|
55055
|
+
}
|
|
52139
55056
|
if (isRuntimeComplexNumber(A)) {
|
|
52140
55057
|
const { re, im } = A;
|
|
52141
55058
|
if (re === 0 && im === 0)
|
|
@@ -52488,6 +55405,67 @@ registerIBuiltin({
|
|
|
52488
55405
|
return { outputTypes: outs, apply: (args, n) => bandwidthApply(args, n) };
|
|
52489
55406
|
}
|
|
52490
55407
|
});
|
|
55408
|
+
function isTriangularValue(A, upper) {
|
|
55409
|
+
if (isRuntimeNumber(A) || isRuntimeComplexNumber(A)) return true;
|
|
55410
|
+
if (isRuntimeSparseMatrix(A))
|
|
55411
|
+
return upper ? sparseIsUpper(A) : sparseIsLower(A);
|
|
55412
|
+
if (isRuntimeTensor(A)) {
|
|
55413
|
+
if (A.shape.length > 2) return false;
|
|
55414
|
+
const [m, n] = tensorSize2D(A);
|
|
55415
|
+
for (let j = 0; j < n; j++)
|
|
55416
|
+
for (let i = 0; i < m; i++) {
|
|
55417
|
+
if (upper ? i <= j : i >= j) continue;
|
|
55418
|
+
const idx = colMajorIndex(i, j, m);
|
|
55419
|
+
if (A.data[idx] !== 0 || A.imag && A.imag[idx] !== 0) return false;
|
|
55420
|
+
}
|
|
55421
|
+
return true;
|
|
55422
|
+
}
|
|
55423
|
+
throw new RuntimeError("istriu: argument must be a numeric matrix");
|
|
55424
|
+
}
|
|
55425
|
+
for (const [name, upper] of [
|
|
55426
|
+
["istriu", true],
|
|
55427
|
+
["istril", false]
|
|
55428
|
+
]) {
|
|
55429
|
+
registerIBuiltin({
|
|
55430
|
+
name,
|
|
55431
|
+
help: {
|
|
55432
|
+
signatures: [`tf = ${name}(A)`],
|
|
55433
|
+
description: `True if A is ${upper ? "upper" : "lower"} triangular (all entries ${upper ? "below" : "above"} the main diagonal are zero). Works for dense and sparse matrices.`
|
|
55434
|
+
},
|
|
55435
|
+
resolve: (argTypes, nargout) => {
|
|
55436
|
+
if (nargout > 1 || argTypes.length !== 1) return null;
|
|
55437
|
+
if (!isNumericJitType(argTypes[0])) return null;
|
|
55438
|
+
return {
|
|
55439
|
+
outputTypes: [{ kind: "boolean" }],
|
|
55440
|
+
apply: (args) => RTV.logical(isTriangularValue(args[0], upper))
|
|
55441
|
+
};
|
|
55442
|
+
}
|
|
55443
|
+
});
|
|
55444
|
+
}
|
|
55445
|
+
registerIBuiltin({
|
|
55446
|
+
name: "isbanded",
|
|
55447
|
+
help: {
|
|
55448
|
+
signatures: ["tf = isbanded(A, lower, upper)"],
|
|
55449
|
+
description: "True if A has lower bandwidth at most `lower` and upper bandwidth at most `upper`. Works for dense and sparse matrices."
|
|
55450
|
+
},
|
|
55451
|
+
resolve: (argTypes, nargout) => {
|
|
55452
|
+
if (nargout > 1 || argTypes.length !== 3) return null;
|
|
55453
|
+
if (!isNumericJitType(argTypes[0])) return null;
|
|
55454
|
+
return {
|
|
55455
|
+
outputTypes: [{ kind: "boolean" }],
|
|
55456
|
+
apply: (args) => {
|
|
55457
|
+
const lo = toNumber(args[1]);
|
|
55458
|
+
const up = toNumber(args[2]);
|
|
55459
|
+
if (lo < 0 || up < 0 || !Number.isInteger(lo) || !Number.isInteger(up))
|
|
55460
|
+
throw new RuntimeError(
|
|
55461
|
+
"isbanded: bandwidths must be nonnegative integers"
|
|
55462
|
+
);
|
|
55463
|
+
const [l, u] = computeBandwidth(args[0]);
|
|
55464
|
+
return RTV.logical(l <= lo && u <= up);
|
|
55465
|
+
}
|
|
55466
|
+
};
|
|
55467
|
+
}
|
|
55468
|
+
});
|
|
52491
55469
|
function computeATA(A_data, m, n) {
|
|
52492
55470
|
const result = allocFloat64Array(n * n);
|
|
52493
55471
|
for (let j = 0; j < n; j++)
|
|
@@ -52856,19 +55834,59 @@ function qrPivotApply(A, m, n, k, econ) {
|
|
|
52856
55834
|
registerIBuiltin({
|
|
52857
55835
|
name: "lu",
|
|
52858
55836
|
resolve: (argTypes, nargout) => {
|
|
52859
|
-
if (nargout < 0 || nargout >
|
|
52860
|
-
if (argTypes.length < 1 || argTypes.length >
|
|
55837
|
+
if (nargout < 0 || nargout > 4) return null;
|
|
55838
|
+
if (argTypes.length < 1 || argTypes.length > 3) return null;
|
|
52861
55839
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
52862
|
-
const
|
|
55840
|
+
const sparse = argTypes[0].kind === "sparse_matrix";
|
|
55841
|
+
if (!sparse && (nargout > 3 || argTypes.length > 2)) return null;
|
|
55842
|
+
const t = sparse ? SPARSE_TYPE : tensorType();
|
|
52863
55843
|
const wrapped = (args, n) => withScratch(() => luApply(args, n));
|
|
52864
55844
|
if (nargout <= 1) return { outputTypes: [t], apply: wrapped };
|
|
52865
55845
|
if (nargout === 2) return { outputTypes: [t, t], apply: wrapped };
|
|
52866
|
-
return { outputTypes: [t, t, t], apply: wrapped };
|
|
55846
|
+
if (nargout === 3) return { outputTypes: [t, t, t], apply: wrapped };
|
|
55847
|
+
return { outputTypes: [t, t, t, t], apply: wrapped };
|
|
52867
55848
|
}
|
|
52868
55849
|
});
|
|
55850
|
+
function sparseLuApply(S, args, nargout) {
|
|
55851
|
+
let outputForm = "matrix";
|
|
55852
|
+
let tol = nargout >= 4 ? 0.1 : 1;
|
|
55853
|
+
for (const opt of args.slice(1)) {
|
|
55854
|
+
if (isRuntimeNumber(opt)) {
|
|
55855
|
+
if (!(opt >= 0 && opt <= 1))
|
|
55856
|
+
throw new RuntimeError("lu: pivot threshold must be in [0, 1]");
|
|
55857
|
+
tol = opt;
|
|
55858
|
+
} else {
|
|
55859
|
+
const form = parseLuOutputForm(opt);
|
|
55860
|
+
if (form === null)
|
|
55861
|
+
throw new RuntimeError("lu: outputForm must be 'matrix' or 'vector'");
|
|
55862
|
+
outputForm = form;
|
|
55863
|
+
}
|
|
55864
|
+
}
|
|
55865
|
+
const q = nargout >= 4 ? columnOrdering(S) : null;
|
|
55866
|
+
const res = sparseLu(S, q, tol);
|
|
55867
|
+
const { L, U, p: p2 } = res;
|
|
55868
|
+
if (nargout <= 1) {
|
|
55869
|
+
return mSub(mAdd(L, U), speyeSparse(Math.min(S.m, S.n)));
|
|
55870
|
+
}
|
|
55871
|
+
if (nargout === 2) {
|
|
55872
|
+
const Lperm = sparsePermute(L, invertPerm(p2), identityPerm(L.n));
|
|
55873
|
+
return [Lperm, U];
|
|
55874
|
+
}
|
|
55875
|
+
const permOut = (perm) => outputForm === "vector" ? permVectorTensor(perm) : permutationMatrix(perm);
|
|
55876
|
+
if (nargout === 3) return [L, U, permOut(p2)];
|
|
55877
|
+
const Q = outputForm === "vector" ? permVectorTensor(res.q) : sparseTranspose(permutationMatrix(res.q));
|
|
55878
|
+
return [L, U, permOut(p2), Q];
|
|
55879
|
+
}
|
|
52869
55880
|
function luApply(args, nargout) {
|
|
52870
55881
|
if (args.length < 1)
|
|
52871
55882
|
throw new RuntimeError("lu requires at least 1 argument");
|
|
55883
|
+
if (isRuntimeSparseMatrix(args[0]) && !args[0].pi)
|
|
55884
|
+
return sparseLuApply(args[0], args, nargout);
|
|
55885
|
+
if (isRuntimeSparseMatrix(args[0])) {
|
|
55886
|
+
const dense = luApply([sparseToDense(args[0]), ...args.slice(1)], nargout);
|
|
55887
|
+
const toSp = (v) => isRuntimeTensor(v) ? denseToSparse(v) : v;
|
|
55888
|
+
return Array.isArray(dense) ? dense.map(toSp) : toSp(dense);
|
|
55889
|
+
}
|
|
52872
55890
|
const outputForm = args.length >= 2 ? parseLuOutputForm(args[1]) : "matrix";
|
|
52873
55891
|
if (outputForm === null)
|
|
52874
55892
|
throw new RuntimeError("lu: outputForm must be 'matrix' or 'vector'");
|
|
@@ -52987,7 +56005,7 @@ function ipivToPermVector(ipiv, m) {
|
|
|
52987
56005
|
registerIBuiltin({
|
|
52988
56006
|
name: "eig",
|
|
52989
56007
|
resolve: (argTypes, nargout) => {
|
|
52990
|
-
if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length >
|
|
56008
|
+
if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 4)
|
|
52991
56009
|
return null;
|
|
52992
56010
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
52993
56011
|
const c = tensorType(true);
|
|
@@ -53002,7 +56020,9 @@ function eigApply(args, nargout) {
|
|
|
53002
56020
|
if (args.length < 1)
|
|
53003
56021
|
throw new RuntimeError("eig requires at least 1 argument");
|
|
53004
56022
|
const A = args[0];
|
|
53005
|
-
const { balance, outputForm } = parseEigOptionsRuntime(args);
|
|
56023
|
+
const { B, balance, outputForm, algorithm } = parseEigOptionsRuntime(args);
|
|
56024
|
+
if (B !== void 0)
|
|
56025
|
+
return eigGeneralizedApply(A, B, nargout, outputForm, algorithm);
|
|
53006
56026
|
if (isRuntimeNumber(A)) {
|
|
53007
56027
|
const val = A;
|
|
53008
56028
|
if (nargout <= 1) return RTV.num(val);
|
|
@@ -53019,6 +56039,10 @@ function eigApply(args, nargout) {
|
|
|
53019
56039
|
const [m, n] = tensorSize2D(A);
|
|
53020
56040
|
if (m !== n) throw new RuntimeError("eig: input must be a square matrix");
|
|
53021
56041
|
const computeVL = nargout >= 3, computeVR = nargout >= 2;
|
|
56042
|
+
if (isExactlyHermitian(A, n)) {
|
|
56043
|
+
const symResult = eigSymmetricApply(A, n, nargout, outputForm);
|
|
56044
|
+
if (symResult) return symResult;
|
|
56045
|
+
}
|
|
53022
56046
|
if (A.imag) {
|
|
53023
56047
|
const bridge2 = getEffectiveBridge("eigComplex", "eigComplex");
|
|
53024
56048
|
if (!bridge2.eigComplex)
|
|
@@ -53054,19 +56078,369 @@ function eigApply(args, nargout) {
|
|
|
53054
56078
|
const Wout = computeVL && VL ? buildEigenvectorMatrix(VL, wi, n, hasComplex) : RTV.tensor(allocFloat64Array(n * n), [n, n]);
|
|
53055
56079
|
return [Vout, Dout, Wout];
|
|
53056
56080
|
}
|
|
56081
|
+
function isExactlyHermitian(A, n) {
|
|
56082
|
+
const re = A.data;
|
|
56083
|
+
const im = A.imag;
|
|
56084
|
+
for (let j = 0; j < n; j++) {
|
|
56085
|
+
if (im && im[j + j * n] !== 0) return false;
|
|
56086
|
+
const dj = re[j + j * n];
|
|
56087
|
+
if (Number.isNaN(dj)) return false;
|
|
56088
|
+
for (let i = j + 1; i < n; i++) {
|
|
56089
|
+
if (re[i + j * n] !== re[j + i * n]) return false;
|
|
56090
|
+
if (im && im[i + j * n] !== -im[j + i * n]) return false;
|
|
56091
|
+
}
|
|
56092
|
+
}
|
|
56093
|
+
return true;
|
|
56094
|
+
}
|
|
56095
|
+
function eigSymmetricApply(A, n, nargout, outputForm) {
|
|
56096
|
+
const computeV = nargout >= 2;
|
|
56097
|
+
let w;
|
|
56098
|
+
let VRe;
|
|
56099
|
+
let VIm;
|
|
56100
|
+
if (A.imag) {
|
|
56101
|
+
const bridge = getEffectiveBridge("eigHerm", "eigHerm");
|
|
56102
|
+
if (!bridge.eigHerm) return null;
|
|
56103
|
+
const r = bridge.eigHerm(toF64(A.data), toF64(A.imag), n, computeV);
|
|
56104
|
+
if (!r) return null;
|
|
56105
|
+
w = r.w;
|
|
56106
|
+
VRe = r.VRe;
|
|
56107
|
+
VIm = r.VIm;
|
|
56108
|
+
} else {
|
|
56109
|
+
const bridge = getEffectiveBridge("eigSym", "eigSym");
|
|
56110
|
+
if (!bridge.eigSym) return null;
|
|
56111
|
+
const r = bridge.eigSym(toF64(A.data), n, computeV);
|
|
56112
|
+
if (!r) return null;
|
|
56113
|
+
w = r.w;
|
|
56114
|
+
VRe = r.V;
|
|
56115
|
+
}
|
|
56116
|
+
if (nargout <= 1) return RTV.tensor(w, [n, 1]);
|
|
56117
|
+
const makeV = () => VRe ? maybeComplexTensor(
|
|
56118
|
+
allocFloat64Array(VRe),
|
|
56119
|
+
[n, n],
|
|
56120
|
+
VIm ? allocFloat64Array(VIm) : void 0
|
|
56121
|
+
) : RTV.tensor(allocFloat64Array(n * n), [n, n]);
|
|
56122
|
+
const Vout = makeV();
|
|
56123
|
+
const Dout = outputForm === "vector" ? RTV.tensor(allocFloat64Array(w), [n, 1]) : buildDiagMatrix(w, void 0, n);
|
|
56124
|
+
if (nargout === 2) return [Vout, Dout];
|
|
56125
|
+
return [Vout, Dout, makeV()];
|
|
56126
|
+
}
|
|
53057
56127
|
function parseEigOptionsRuntime(args) {
|
|
53058
|
-
let balance = true, outputForm = "matrix";
|
|
53059
|
-
|
|
56128
|
+
let balance = true, outputForm = "matrix", algorithm = "auto";
|
|
56129
|
+
let B;
|
|
56130
|
+
let first = 1;
|
|
56131
|
+
if (args.length >= 2 && !isStringLikeArg(args[1])) {
|
|
56132
|
+
B = args[1];
|
|
56133
|
+
first = 2;
|
|
56134
|
+
}
|
|
56135
|
+
for (let i = first; i < args.length; i++) {
|
|
53060
56136
|
const arg = args[i];
|
|
53061
|
-
if (
|
|
53062
|
-
|
|
53063
|
-
|
|
53064
|
-
|
|
53065
|
-
|
|
53066
|
-
|
|
56137
|
+
if (!isStringLikeArg(arg))
|
|
56138
|
+
throw new RuntimeError(
|
|
56139
|
+
"eig: option arguments must be character vectors or strings"
|
|
56140
|
+
);
|
|
56141
|
+
const val = parseStringArgLower(arg);
|
|
56142
|
+
if (val === "nobalance") balance = false;
|
|
56143
|
+
else if (val === "balance") balance = true;
|
|
56144
|
+
else if (val === "vector") outputForm = "vector";
|
|
56145
|
+
else if (val === "matrix") outputForm = "matrix";
|
|
56146
|
+
else if (val === "chol" || val === "qz") algorithm = val;
|
|
56147
|
+
else throw new RuntimeError(`eig: unknown option '${val}'`);
|
|
56148
|
+
}
|
|
56149
|
+
if (algorithm !== "auto" && B === void 0)
|
|
56150
|
+
throw new RuntimeError(
|
|
56151
|
+
`eig: the '${algorithm}' algorithm applies only to eig(A, B)`
|
|
56152
|
+
);
|
|
56153
|
+
return { B, balance, outputForm, algorithm };
|
|
56154
|
+
}
|
|
56155
|
+
function isStringLikeArg(arg) {
|
|
56156
|
+
return isRuntimeString(arg) || isRuntimeChar(arg);
|
|
56157
|
+
}
|
|
56158
|
+
function toSplitSquare(v, name) {
|
|
56159
|
+
if (isRuntimeNumber(v))
|
|
56160
|
+
return { M: { re: allocFloat64Array([v]), im: null }, n: 1 };
|
|
56161
|
+
if (isRuntimeComplexNumber(v))
|
|
56162
|
+
return {
|
|
56163
|
+
M: { re: allocFloat64Array([v.re]), im: allocFloat64Array([v.im]) },
|
|
56164
|
+
n: 1
|
|
56165
|
+
};
|
|
56166
|
+
let t = v;
|
|
56167
|
+
if (isRuntimeSparseMatrix(t))
|
|
56168
|
+
t = sparseToDense(
|
|
56169
|
+
t
|
|
56170
|
+
);
|
|
56171
|
+
if (!isRuntimeTensor(t))
|
|
56172
|
+
throw new RuntimeError(`eig: ${name} must be a numeric matrix`);
|
|
56173
|
+
const [rows, cols] = tensorSize2D(t);
|
|
56174
|
+
if (rows !== cols)
|
|
56175
|
+
throw new RuntimeError(`eig: ${name} must be a square matrix`);
|
|
56176
|
+
return {
|
|
56177
|
+
M: { re: toF64(t.data), im: t.imag ? toF64(t.imag) : null },
|
|
56178
|
+
n: rows
|
|
56179
|
+
};
|
|
56180
|
+
}
|
|
56181
|
+
function splitIsHermitian(M, n) {
|
|
56182
|
+
for (let j = 0; j < n; j++) {
|
|
56183
|
+
if (M.im && M.im[j + j * n] !== 0) return false;
|
|
56184
|
+
if (Number.isNaN(M.re[j + j * n])) return false;
|
|
56185
|
+
for (let i = j + 1; i < n; i++) {
|
|
56186
|
+
if (M.re[i + j * n] !== M.re[j + i * n]) return false;
|
|
56187
|
+
if (M.im && M.im[i + j * n] !== -M.im[j + i * n]) return false;
|
|
53067
56188
|
}
|
|
53068
56189
|
}
|
|
53069
|
-
return
|
|
56190
|
+
return true;
|
|
56191
|
+
}
|
|
56192
|
+
function eigGeneralizedApply(Aval, Bval, nargout, outputForm, algorithm) {
|
|
56193
|
+
const { M: A, n } = toSplitSquare(Aval, "A");
|
|
56194
|
+
const { M: B, n: nB } = toSplitSquare(Bval, "B");
|
|
56195
|
+
if (n !== nB) throw new RuntimeError("eig: A and B must be the same size");
|
|
56196
|
+
if (algorithm !== "qz" && splitIsHermitian(A, n) && splitIsHermitian(B, n)) {
|
|
56197
|
+
const R = choleskyFactor(B, n);
|
|
56198
|
+
if (R) return eigSymmetricDefinite(A, R, n, nargout, outputForm);
|
|
56199
|
+
if (algorithm === "chol")
|
|
56200
|
+
throw new RuntimeError(
|
|
56201
|
+
"eig: the 'chol' algorithm requires B to be symmetric positive definite"
|
|
56202
|
+
);
|
|
56203
|
+
}
|
|
56204
|
+
return eigGeneralizedQz(A, B, n, nargout, outputForm);
|
|
56205
|
+
}
|
|
56206
|
+
function choleskyFactor(B, n) {
|
|
56207
|
+
if (B.im) {
|
|
56208
|
+
const bridge2 = getEffectiveBridge("cholComplex", "cholComplex");
|
|
56209
|
+
if (!bridge2.cholComplex) return null;
|
|
56210
|
+
const r2 = bridge2.cholComplex(B.re, B.im, n, true);
|
|
56211
|
+
if (!r2 || r2.info !== 0) return null;
|
|
56212
|
+
return { re: r2.RRe, im: r2.RIm };
|
|
56213
|
+
}
|
|
56214
|
+
const bridge = getEffectiveBridge("chol", "chol");
|
|
56215
|
+
if (!bridge.chol) return null;
|
|
56216
|
+
const r = bridge.chol(B.re, n, true);
|
|
56217
|
+
if (!r || r.info !== 0) return null;
|
|
56218
|
+
return { re: r.R, im: null };
|
|
56219
|
+
}
|
|
56220
|
+
function eigSymmetricDefinite(A, R, n, nargout, outputForm) {
|
|
56221
|
+
const complex = !!(A.im || R.im);
|
|
56222
|
+
const Y = solveLeftConjTransposeUpper(R, A, n, complex);
|
|
56223
|
+
const C = solveRightUpper(Y, R, n, complex);
|
|
56224
|
+
symmetrizeInPlace(C, n);
|
|
56225
|
+
const computeV = nargout >= 2;
|
|
56226
|
+
let w;
|
|
56227
|
+
let SRe;
|
|
56228
|
+
let SIm;
|
|
56229
|
+
if (complex) {
|
|
56230
|
+
const bridge = getEffectiveBridge("eigHerm", "eigHerm");
|
|
56231
|
+
if (!bridge.eigHerm)
|
|
56232
|
+
throw new RuntimeError("eig: Hermitian eig bridge not available");
|
|
56233
|
+
const r = bridge.eigHerm(
|
|
56234
|
+
C.re,
|
|
56235
|
+
C.im ?? allocFloat64Array(n * n),
|
|
56236
|
+
n,
|
|
56237
|
+
computeV
|
|
56238
|
+
);
|
|
56239
|
+
w = r.w;
|
|
56240
|
+
SRe = r.VRe;
|
|
56241
|
+
SIm = r.VIm;
|
|
56242
|
+
} else {
|
|
56243
|
+
const bridge = getEffectiveBridge("eigSym", "eigSym");
|
|
56244
|
+
if (!bridge.eigSym)
|
|
56245
|
+
throw new RuntimeError("eig: symmetric eig bridge not available");
|
|
56246
|
+
const r = bridge.eigSym(C.re, n, computeV);
|
|
56247
|
+
w = r.w;
|
|
56248
|
+
SRe = r.V;
|
|
56249
|
+
}
|
|
56250
|
+
if (nargout <= 1) return RTV.tensor(w, [n, 1]);
|
|
56251
|
+
const S = {
|
|
56252
|
+
re: SRe ?? allocFloat64Array(n * n),
|
|
56253
|
+
im: SIm ?? null
|
|
56254
|
+
};
|
|
56255
|
+
const V = SRe ? solveUpper(R, S, n, complex) : S;
|
|
56256
|
+
const makeV = () => maybeComplexTensor(
|
|
56257
|
+
allocFloat64Array(V.re),
|
|
56258
|
+
[n, n],
|
|
56259
|
+
V.im ? allocFloat64Array(V.im) : void 0
|
|
56260
|
+
);
|
|
56261
|
+
const Vout = makeV();
|
|
56262
|
+
const Dout = outputForm === "vector" ? RTV.tensor(allocFloat64Array(w), [n, 1]) : buildDiagMatrix(w, void 0, n);
|
|
56263
|
+
if (nargout === 2) return [Vout, Dout];
|
|
56264
|
+
return [Vout, Dout, makeV()];
|
|
56265
|
+
}
|
|
56266
|
+
function symmetrizeInPlace(M, n) {
|
|
56267
|
+
for (let j = 0; j < n; j++) {
|
|
56268
|
+
if (M.im) M.im[j + j * n] = 0;
|
|
56269
|
+
for (let i = j + 1; i < n; i++) {
|
|
56270
|
+
const a = (M.re[i + j * n] + M.re[j + i * n]) / 2;
|
|
56271
|
+
M.re[i + j * n] = a;
|
|
56272
|
+
M.re[j + i * n] = a;
|
|
56273
|
+
if (M.im) {
|
|
56274
|
+
const b = (M.im[i + j * n] - M.im[j + i * n]) / 2;
|
|
56275
|
+
M.im[i + j * n] = b;
|
|
56276
|
+
M.im[j + i * n] = -b;
|
|
56277
|
+
}
|
|
56278
|
+
}
|
|
56279
|
+
}
|
|
56280
|
+
}
|
|
56281
|
+
function solveLeftConjTransposeUpper(R, Bm, n, complex) {
|
|
56282
|
+
const X = {
|
|
56283
|
+
re: allocFloat64Array(n * n),
|
|
56284
|
+
im: complex ? allocFloat64Array(n * n) : null
|
|
56285
|
+
};
|
|
56286
|
+
for (let c = 0; c < n; c++) {
|
|
56287
|
+
for (let i = 0; i < n; i++) {
|
|
56288
|
+
let sr = Bm.re[i + c * n];
|
|
56289
|
+
let si = Bm.im ? Bm.im[i + c * n] : 0;
|
|
56290
|
+
for (let k = 0; k < i; k++) {
|
|
56291
|
+
const lr = R.re[k + i * n];
|
|
56292
|
+
const li = R.im ? -R.im[k + i * n] : 0;
|
|
56293
|
+
const xr = X.re[k + c * n];
|
|
56294
|
+
const xi = X.im ? X.im[k + c * n] : 0;
|
|
56295
|
+
sr -= lr * xr - li * xi;
|
|
56296
|
+
si -= lr * xi + li * xr;
|
|
56297
|
+
}
|
|
56298
|
+
const dr = R.re[i + i * n];
|
|
56299
|
+
const di = R.im ? -R.im[i + i * n] : 0;
|
|
56300
|
+
const [qr2, qi] = complexDivide2(sr, si, dr, di);
|
|
56301
|
+
X.re[i + c * n] = qr2;
|
|
56302
|
+
if (X.im) X.im[i + c * n] = qi;
|
|
56303
|
+
}
|
|
56304
|
+
}
|
|
56305
|
+
return X;
|
|
56306
|
+
}
|
|
56307
|
+
function solveRightUpper(Y, R, n, complex) {
|
|
56308
|
+
const C = {
|
|
56309
|
+
re: allocFloat64Array(n * n),
|
|
56310
|
+
im: complex ? allocFloat64Array(n * n) : null
|
|
56311
|
+
};
|
|
56312
|
+
for (let j = 0; j < n; j++) {
|
|
56313
|
+
for (let i = 0; i < n; i++) {
|
|
56314
|
+
let sr = Y.re[i + j * n];
|
|
56315
|
+
let si = Y.im ? Y.im[i + j * n] : 0;
|
|
56316
|
+
for (let k = 0; k < j; k++) {
|
|
56317
|
+
const cr = C.re[i + k * n];
|
|
56318
|
+
const ci = C.im ? C.im[i + k * n] : 0;
|
|
56319
|
+
const rr = R.re[k + j * n];
|
|
56320
|
+
const ri = R.im ? R.im[k + j * n] : 0;
|
|
56321
|
+
sr -= cr * rr - ci * ri;
|
|
56322
|
+
si -= cr * ri + ci * rr;
|
|
56323
|
+
}
|
|
56324
|
+
const dr = R.re[j + j * n];
|
|
56325
|
+
const di = R.im ? R.im[j + j * n] : 0;
|
|
56326
|
+
const [qr2, qi] = complexDivide2(sr, si, dr, di);
|
|
56327
|
+
C.re[i + j * n] = qr2;
|
|
56328
|
+
if (C.im) C.im[i + j * n] = qi;
|
|
56329
|
+
}
|
|
56330
|
+
}
|
|
56331
|
+
return C;
|
|
56332
|
+
}
|
|
56333
|
+
function solveUpper(R, S, n, complex) {
|
|
56334
|
+
const V = {
|
|
56335
|
+
re: allocFloat64Array(n * n),
|
|
56336
|
+
im: complex ? allocFloat64Array(n * n) : null
|
|
56337
|
+
};
|
|
56338
|
+
for (let c = 0; c < n; c++) {
|
|
56339
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
56340
|
+
let sr = S.re[i + c * n];
|
|
56341
|
+
let si = S.im ? S.im[i + c * n] : 0;
|
|
56342
|
+
for (let k = i + 1; k < n; k++) {
|
|
56343
|
+
const rr = R.re[i + k * n];
|
|
56344
|
+
const ri = R.im ? R.im[i + k * n] : 0;
|
|
56345
|
+
const vr = V.re[k + c * n];
|
|
56346
|
+
const vi = V.im ? V.im[k + c * n] : 0;
|
|
56347
|
+
sr -= rr * vr - ri * vi;
|
|
56348
|
+
si -= rr * vi + ri * vr;
|
|
56349
|
+
}
|
|
56350
|
+
const dr = R.re[i + i * n];
|
|
56351
|
+
const di = R.im ? R.im[i + i * n] : 0;
|
|
56352
|
+
const [qr2, qi] = complexDivide2(sr, si, dr, di);
|
|
56353
|
+
V.re[i + c * n] = qr2;
|
|
56354
|
+
if (V.im) V.im[i + c * n] = qi;
|
|
56355
|
+
}
|
|
56356
|
+
}
|
|
56357
|
+
return V;
|
|
56358
|
+
}
|
|
56359
|
+
function complexDivide2(ar, ai, br, bi) {
|
|
56360
|
+
if (bi === 0) return [ar / br, ai / br];
|
|
56361
|
+
if (Math.abs(br) >= Math.abs(bi)) {
|
|
56362
|
+
const r2 = bi / br;
|
|
56363
|
+
const t2 = br + bi * r2;
|
|
56364
|
+
return [(ar + ai * r2) / t2, (ai - ar * r2) / t2];
|
|
56365
|
+
}
|
|
56366
|
+
const r = br / bi;
|
|
56367
|
+
const t = br * r + bi;
|
|
56368
|
+
return [(ar * r + ai) / t, (ai * r - ar) / t];
|
|
56369
|
+
}
|
|
56370
|
+
function eigGeneralizedQz(A, B, n, nargout, outputForm) {
|
|
56371
|
+
const computeEigvecs = nargout >= 2;
|
|
56372
|
+
const wr = allocFloat64Array(n);
|
|
56373
|
+
const wi = allocFloat64Array(n);
|
|
56374
|
+
let V = null;
|
|
56375
|
+
let W = null;
|
|
56376
|
+
if (A.im || B.im) {
|
|
56377
|
+
const bridge = getEffectiveBridge("qzComplex", "qzComplex");
|
|
56378
|
+
if (!bridge.qzComplex) throw generalizedUnsupported();
|
|
56379
|
+
const r = bridge.qzComplex(
|
|
56380
|
+
A.re,
|
|
56381
|
+
A.im ?? allocFloat64Array(n * n),
|
|
56382
|
+
B.re,
|
|
56383
|
+
B.im ?? allocFloat64Array(n * n),
|
|
56384
|
+
n,
|
|
56385
|
+
computeEigvecs
|
|
56386
|
+
);
|
|
56387
|
+
if (!r) throw new RuntimeError("eig: complex QZ failed");
|
|
56388
|
+
for (let i = 0; i < n; i++) {
|
|
56389
|
+
const [qr2, qi] = complexDivide2(
|
|
56390
|
+
r.alphaRe[i],
|
|
56391
|
+
r.alphaIm[i],
|
|
56392
|
+
r.betaRe[i],
|
|
56393
|
+
r.betaIm[i]
|
|
56394
|
+
);
|
|
56395
|
+
wr[i] = qr2;
|
|
56396
|
+
wi[i] = qi;
|
|
56397
|
+
}
|
|
56398
|
+
if (computeEigvecs) {
|
|
56399
|
+
if (!r.VRe || !r.VIm || !r.WRe || !r.WIm)
|
|
56400
|
+
throw new RuntimeError(
|
|
56401
|
+
"eig: failed to compute generalized eigenvectors"
|
|
56402
|
+
);
|
|
56403
|
+
V = maybeComplexTensor(
|
|
56404
|
+
allocFloat64Array(r.VRe),
|
|
56405
|
+
[n, n],
|
|
56406
|
+
allocFloat64Array(r.VIm)
|
|
56407
|
+
);
|
|
56408
|
+
W = maybeComplexTensor(
|
|
56409
|
+
allocFloat64Array(r.WRe),
|
|
56410
|
+
[n, n],
|
|
56411
|
+
allocFloat64Array(r.WIm)
|
|
56412
|
+
);
|
|
56413
|
+
}
|
|
56414
|
+
} else {
|
|
56415
|
+
const bridge = getEffectiveBridge("qz", "qz");
|
|
56416
|
+
if (!bridge.qz) throw generalizedUnsupported();
|
|
56417
|
+
const r = bridge.qz(A.re, B.re, n, computeEigvecs);
|
|
56418
|
+
if (!r) throw new RuntimeError("eig: real QZ failed");
|
|
56419
|
+
let hasComplex = false;
|
|
56420
|
+
for (let i = 0; i < n; i++) {
|
|
56421
|
+
const beta = r.beta[i];
|
|
56422
|
+
wr[i] = r.alphar[i] / beta;
|
|
56423
|
+
wi[i] = r.alphai[i] === 0 && beta === 0 ? 0 : r.alphai[i] / beta;
|
|
56424
|
+
if (r.alphai[i] !== 0) hasComplex = true;
|
|
56425
|
+
}
|
|
56426
|
+
if (computeEigvecs) {
|
|
56427
|
+
if (!r.V || !r.W)
|
|
56428
|
+
throw new RuntimeError(
|
|
56429
|
+
"eig: failed to compute generalized eigenvectors"
|
|
56430
|
+
);
|
|
56431
|
+
V = buildEigenvectorMatrix(r.V, r.alphai, n, hasComplex);
|
|
56432
|
+
W = buildEigenvectorMatrix(r.W, r.alphai, n, hasComplex);
|
|
56433
|
+
}
|
|
56434
|
+
}
|
|
56435
|
+
if (nargout <= 1) return maybeComplexTensor(wr, [n, 1], wi);
|
|
56436
|
+
const Dout = outputForm === "vector" ? maybeComplexTensor(wr, [n, 1], wi) : buildDiagMatrix(wr, wi, n);
|
|
56437
|
+
if (nargout === 2) return [V, Dout];
|
|
56438
|
+
return [V, Dout, W];
|
|
56439
|
+
}
|
|
56440
|
+
function generalizedUnsupported() {
|
|
56441
|
+
return new RuntimeError(
|
|
56442
|
+
"eig: the generalized eigenvalue problem eig(A, B) with a non symmetric-definite pencil requires the native LAPACK addon"
|
|
56443
|
+
);
|
|
53070
56444
|
}
|
|
53071
56445
|
registerIBuiltin({
|
|
53072
56446
|
name: "chol",
|
|
@@ -53074,13 +56448,31 @@ registerIBuiltin({
|
|
|
53074
56448
|
if (nargout < 0 || nargout > 3 || argTypes.length < 1 || argTypes.length > 3)
|
|
53075
56449
|
return null;
|
|
53076
56450
|
if (!isNumericJitType(argTypes[0])) return null;
|
|
53077
|
-
const t = tensorType();
|
|
56451
|
+
const t = argTypes[0].kind === "sparse_matrix" ? SPARSE_TYPE : tensorType();
|
|
53078
56452
|
const wrapped = (args, n) => withScratch(() => cholApply(args, n));
|
|
53079
56453
|
if (nargout <= 1) return { outputTypes: [t], apply: wrapped };
|
|
53080
56454
|
if (nargout === 2) return { outputTypes: [t, NUM], apply: wrapped };
|
|
53081
56455
|
return { outputTypes: [t, NUM, t], apply: wrapped };
|
|
53082
56456
|
}
|
|
53083
56457
|
});
|
|
56458
|
+
function sparseCholApply(S, upper, outputForm, nargout) {
|
|
56459
|
+
if (S.m !== S.n) throw new RuntimeError("chol: Matrix must be square.");
|
|
56460
|
+
const n = S.n;
|
|
56461
|
+
const perm = nargout >= 3 ? minimumDegreeOrdering(S) : identityPerm(n);
|
|
56462
|
+
const A = nargout >= 3 ? sparsePermute(S, perm, perm) : S;
|
|
56463
|
+
const res = sparseChol(A);
|
|
56464
|
+
const R = upper ? sparseTranspose(res.L) : res.L;
|
|
56465
|
+
const permOut = () => outputForm === "vector" ? permVectorTensor(perm) : permutationMatrix(invertPerm(perm));
|
|
56466
|
+
if (!res.ok) {
|
|
56467
|
+
if (nargout < 2)
|
|
56468
|
+
throw new RuntimeError("chol: Matrix must be positive definite.");
|
|
56469
|
+
if (nargout >= 3) return [R, RTV.num(res.p), permOut()];
|
|
56470
|
+
return [R, RTV.num(res.p)];
|
|
56471
|
+
}
|
|
56472
|
+
if (nargout >= 3) return [R, RTV.num(0), permOut()];
|
|
56473
|
+
if (nargout === 2) return [R, RTV.num(0)];
|
|
56474
|
+
return R;
|
|
56475
|
+
}
|
|
53084
56476
|
function cholApply(args, nargout) {
|
|
53085
56477
|
if (args.length < 1)
|
|
53086
56478
|
throw new RuntimeError("chol requires at least 1 argument");
|
|
@@ -53088,10 +56480,9 @@ function cholApply(args, nargout) {
|
|
|
53088
56480
|
const inputIsSparse = isRuntimeSparseMatrix(A);
|
|
53089
56481
|
if (nargout >= 3 && !inputIsSparse)
|
|
53090
56482
|
throw new RuntimeError("Third output only available for sparse matrices.");
|
|
53091
|
-
|
|
53092
|
-
|
|
53093
|
-
|
|
53094
|
-
);
|
|
56483
|
+
const sparseInput = isRuntimeSparseMatrix(A) && !A.pi ? A : null;
|
|
56484
|
+
if (inputIsSparse && !sparseInput)
|
|
56485
|
+
A = sparseToDense(A);
|
|
53095
56486
|
let triangle = "upper";
|
|
53096
56487
|
let outputForm = "matrix";
|
|
53097
56488
|
if (args.length === 2) {
|
|
@@ -53110,6 +56501,8 @@ function cholApply(args, nargout) {
|
|
|
53110
56501
|
outputForm = form;
|
|
53111
56502
|
}
|
|
53112
56503
|
const upper = triangle === "upper";
|
|
56504
|
+
if (sparseInput)
|
|
56505
|
+
return sparseCholApply(sparseInput, upper, outputForm, nargout);
|
|
53113
56506
|
if (isRuntimeNumber(A)) {
|
|
53114
56507
|
const val = A;
|
|
53115
56508
|
if (val <= 0) {
|
|
@@ -53527,15 +56920,28 @@ defineBuiltin({
|
|
|
53527
56920
|
if (nargout > 1 || argTypes.length !== 2) return null;
|
|
53528
56921
|
if (!isNumericJitType(argTypes[0]) || !isNumericJitType(argTypes[1]))
|
|
53529
56922
|
return null;
|
|
56923
|
+
if (argTypes.some((t) => t.kind === "sparse_matrix"))
|
|
56924
|
+
return [
|
|
56925
|
+
{
|
|
56926
|
+
kind: "sparse_matrix",
|
|
56927
|
+
isComplex: argTypes.some(
|
|
56928
|
+
(t) => t.kind === "sparse_matrix" && t.isComplex
|
|
56929
|
+
)
|
|
56930
|
+
}
|
|
56931
|
+
];
|
|
53530
56932
|
return [tensorType()];
|
|
53531
56933
|
},
|
|
53532
56934
|
apply: (args) => {
|
|
53533
56935
|
if (args.length !== 2)
|
|
53534
56936
|
throw new RuntimeError("kron requires 2 arguments");
|
|
56937
|
+
if (isRuntimeSparseMatrix(args[0]) || isRuntimeSparseMatrix(args[1]))
|
|
56938
|
+
return sparseKron(
|
|
56939
|
+
toSparseOperand(args[0], "kron"),
|
|
56940
|
+
toSparseOperand(args[1], "kron")
|
|
56941
|
+
);
|
|
53535
56942
|
const coerce = (v) => {
|
|
53536
56943
|
if (isRuntimeNumber(v))
|
|
53537
56944
|
return RTV.tensor(allocFloat64Array([v]), [1, 1]);
|
|
53538
|
-
if (isRuntimeSparseMatrix(v)) return sparseToDense(v);
|
|
53539
56945
|
if (isRuntimeTensor(v)) return v;
|
|
53540
56946
|
throw new RuntimeError("kron: arguments must be numeric");
|
|
53541
56947
|
};
|
|
@@ -59442,130 +62848,6 @@ registerIBuiltin({
|
|
|
59442
62848
|
}
|
|
59443
62849
|
});
|
|
59444
62850
|
|
|
59445
|
-
// src/numbl-core/helpers/prng.ts
|
|
59446
|
-
var _rngState = null;
|
|
59447
|
-
var _rngSeed = 0;
|
|
59448
|
-
var _bmSpare = null;
|
|
59449
|
-
function setRngShuffle() {
|
|
59450
|
-
_rngState = null;
|
|
59451
|
-
_rngSeed = 0;
|
|
59452
|
-
_bmSpare = null;
|
|
59453
|
-
}
|
|
59454
|
-
function setRngSeed(seed) {
|
|
59455
|
-
_rngSeed = seed;
|
|
59456
|
-
}
|
|
59457
|
-
function splitmix32(seed) {
|
|
59458
|
-
let s = seed | 0;
|
|
59459
|
-
return () => {
|
|
59460
|
-
s = s + 2654435769 | 0;
|
|
59461
|
-
let z = s;
|
|
59462
|
-
z = Math.imul(z ^ z >>> 16, 2246822507);
|
|
59463
|
-
z = Math.imul(z ^ z >>> 13, 3266489909);
|
|
59464
|
-
return (z ^ z >>> 16) >>> 0;
|
|
59465
|
-
};
|
|
59466
|
-
}
|
|
59467
|
-
function seedRng(seed) {
|
|
59468
|
-
_bmSpare = null;
|
|
59469
|
-
const sm = splitmix32(seed);
|
|
59470
|
-
_rngState = new Uint32Array([sm(), sm(), sm(), sm()]);
|
|
59471
|
-
if (_rngState[0] === 0 && _rngState[1] === 0 && _rngState[2] === 0 && _rngState[3] === 0) {
|
|
59472
|
-
_rngState[0] = 1;
|
|
59473
|
-
}
|
|
59474
|
-
}
|
|
59475
|
-
function xoshiro128ss() {
|
|
59476
|
-
const s = _rngState;
|
|
59477
|
-
const result = Math.imul(rotl(Math.imul(s[1], 5), 7), 9) >>> 0;
|
|
59478
|
-
const t = s[1] << 9;
|
|
59479
|
-
s[2] ^= s[0];
|
|
59480
|
-
s[3] ^= s[1];
|
|
59481
|
-
s[1] ^= s[2];
|
|
59482
|
-
s[0] ^= s[3];
|
|
59483
|
-
s[2] ^= t;
|
|
59484
|
-
s[3] = rotl(s[3], 11);
|
|
59485
|
-
return result;
|
|
59486
|
-
}
|
|
59487
|
-
function rotl(x, k) {
|
|
59488
|
-
return (x << k | x >>> 32 - k) >>> 0;
|
|
59489
|
-
}
|
|
59490
|
-
function rngRandom() {
|
|
59491
|
-
if (_rngState === null) return Math.random();
|
|
59492
|
-
return (xoshiro128ss() >>> 0) / 4294967296;
|
|
59493
|
-
}
|
|
59494
|
-
function boxMullerRandom() {
|
|
59495
|
-
if (_bmSpare !== null) {
|
|
59496
|
-
const s2 = _bmSpare;
|
|
59497
|
-
_bmSpare = null;
|
|
59498
|
-
return s2;
|
|
59499
|
-
}
|
|
59500
|
-
let u, v, s;
|
|
59501
|
-
do {
|
|
59502
|
-
u = 2 * rngRandom() - 1;
|
|
59503
|
-
v = 2 * rngRandom() - 1;
|
|
59504
|
-
s = u * u + v * v;
|
|
59505
|
-
} while (s >= 1 || s === 0);
|
|
59506
|
-
const mul = Math.sqrt(-2 * Math.log(s) / s);
|
|
59507
|
-
_bmSpare = v * mul;
|
|
59508
|
-
return u * mul;
|
|
59509
|
-
}
|
|
59510
|
-
function fillRandn(data) {
|
|
59511
|
-
if (_rngState !== null) {
|
|
59512
|
-
const bridge = getLapackBridge();
|
|
59513
|
-
if (bridge?.fillRandn) {
|
|
59514
|
-
const r = bridge.fillRandn(
|
|
59515
|
-
_rngState,
|
|
59516
|
-
data.length,
|
|
59517
|
-
_bmSpare ?? 0,
|
|
59518
|
-
_bmSpare !== null
|
|
59519
|
-
);
|
|
59520
|
-
_bmSpare = r.hasSpare ? r.spare : null;
|
|
59521
|
-
data.set(r.data);
|
|
59522
|
-
return;
|
|
59523
|
-
}
|
|
59524
|
-
}
|
|
59525
|
-
const n = data.length;
|
|
59526
|
-
let i = 0;
|
|
59527
|
-
if (_bmSpare !== null && i < n) {
|
|
59528
|
-
data[i++] = _bmSpare;
|
|
59529
|
-
_bmSpare = null;
|
|
59530
|
-
}
|
|
59531
|
-
for (; i + 1 < n; i += 2) {
|
|
59532
|
-
let u, v, s;
|
|
59533
|
-
do {
|
|
59534
|
-
u = 2 * rngRandom() - 1;
|
|
59535
|
-
v = 2 * rngRandom() - 1;
|
|
59536
|
-
s = u * u + v * v;
|
|
59537
|
-
} while (s >= 1 || s === 0);
|
|
59538
|
-
const mul = Math.sqrt(-2 * Math.log(s) / s);
|
|
59539
|
-
data[i] = u * mul;
|
|
59540
|
-
data[i + 1] = v * mul;
|
|
59541
|
-
}
|
|
59542
|
-
if (i < n) {
|
|
59543
|
-
data[i] = boxMullerRandom();
|
|
59544
|
-
}
|
|
59545
|
-
}
|
|
59546
|
-
function getRngStateStruct() {
|
|
59547
|
-
const stateArray = _rngState ? RTV.tensor(allocFloat64Array(Array.from(_rngState).map((v) => v)), [4, 1]) : RTV.tensor(allocFloat64Array(0), [0, 1]);
|
|
59548
|
-
return RTV.struct({
|
|
59549
|
-
Type: RTV.char("twister"),
|
|
59550
|
-
Seed: RTV.num(_rngSeed),
|
|
59551
|
-
State: stateArray
|
|
59552
|
-
});
|
|
59553
|
-
}
|
|
59554
|
-
function restoreRngState(s) {
|
|
59555
|
-
const seedField = s.fields.get("Seed");
|
|
59556
|
-
const stateField = s.fields.get("State");
|
|
59557
|
-
if (seedField === void 0 || stateField === void 0) {
|
|
59558
|
-
throw new RuntimeError("rng: invalid state structure");
|
|
59559
|
-
}
|
|
59560
|
-
_rngSeed = Math.round(toNumber(seedField));
|
|
59561
|
-
if (isRuntimeTensor(stateField) && stateField.data.length === 4) {
|
|
59562
|
-
_rngState = new Uint32Array(4);
|
|
59563
|
-
for (let i = 0; i < 4; i++) _rngState[i] = stateField.data[i] >>> 0;
|
|
59564
|
-
} else {
|
|
59565
|
-
_rngState = null;
|
|
59566
|
-
}
|
|
59567
|
-
}
|
|
59568
|
-
|
|
59569
62851
|
// src/numbl-core/interpreter/builtins/prng.ts
|
|
59570
62852
|
function parseShapeArgs3(rawArgs) {
|
|
59571
62853
|
const args = stripClassNameArgs(rawArgs);
|
|
@@ -63315,7 +66597,7 @@ var H = {
|
|
|
63315
66597
|
},
|
|
63316
66598
|
inv: {
|
|
63317
66599
|
signatures: ["B = inv(A)"],
|
|
63318
|
-
description: "Matrix inverse."
|
|
66600
|
+
description: "Matrix inverse. A sparse A gives a sparse B (computed by sparse LU); prefer A \\ b for solving systems."
|
|
63319
66601
|
},
|
|
63320
66602
|
expm: {
|
|
63321
66603
|
signatures: ["Y = expm(X)"],
|
|
@@ -63326,8 +66608,15 @@ var H = {
|
|
|
63326
66608
|
description: "Sum of diagonal elements."
|
|
63327
66609
|
},
|
|
63328
66610
|
eig: {
|
|
63329
|
-
signatures: [
|
|
63330
|
-
|
|
66611
|
+
signatures: [
|
|
66612
|
+
"E = eig(A)",
|
|
66613
|
+
"[V, D] = eig(A)",
|
|
66614
|
+
"[V, D, W] = eig(A)",
|
|
66615
|
+
"E = eig(A, B)",
|
|
66616
|
+
"[V, D] = eig(A, B)",
|
|
66617
|
+
"eig(A, ..., 'vector' | 'matrix' | 'nobalance' | 'chol' | 'qz')"
|
|
66618
|
+
],
|
|
66619
|
+
description: "Eigenvalues and eigenvectors of a square matrix. With three outputs, W contains left eigenvectors. Symmetric (Hermitian) input gives real eigenvalues in ascending order and an orthonormal eigenvector basis. eig(A, B) solves the generalized problem A*v = lambda*B*v; for a symmetric-definite pencil V is normalized so that V'*B*V = I."
|
|
63331
66620
|
},
|
|
63332
66621
|
eigs: {
|
|
63333
66622
|
signatures: [
|
|
@@ -63350,8 +66639,15 @@ var H = {
|
|
|
63350
66639
|
description: "Singular value decomposition."
|
|
63351
66640
|
},
|
|
63352
66641
|
lu: {
|
|
63353
|
-
signatures: [
|
|
63354
|
-
|
|
66642
|
+
signatures: [
|
|
66643
|
+
"Y = lu(A)",
|
|
66644
|
+
"[L, U] = lu(A)",
|
|
66645
|
+
"[L, U, P] = lu(A)",
|
|
66646
|
+
"[L, U, P] = lu(A, 'vector')",
|
|
66647
|
+
"[L, U, P, Q] = lu(S)",
|
|
66648
|
+
"[L, U, P, Q] = lu(S, thresh)"
|
|
66649
|
+
],
|
|
66650
|
+
description: "LU factorization. With 2 outputs, L includes the permutation. With 3, P is a permutation matrix (or a row vector with 'vector'). Sparse S returns sparse factors from a left-looking LU with threshold partial pivoting; with 4 outputs, Q is a fill-reducing column permutation and P*S*Q = L*U."
|
|
63355
66651
|
},
|
|
63356
66652
|
qr: {
|
|
63357
66653
|
signatures: [
|
|
@@ -63363,8 +66659,14 @@ var H = {
|
|
|
63363
66659
|
description: "QR factorization. With 3 outputs, E is a column permutation matrix (or vector in economy mode)."
|
|
63364
66660
|
},
|
|
63365
66661
|
chol: {
|
|
63366
|
-
signatures: [
|
|
63367
|
-
|
|
66662
|
+
signatures: [
|
|
66663
|
+
"R = chol(A)",
|
|
66664
|
+
"L = chol(A, 'lower')",
|
|
66665
|
+
"[R, p] = chol(A)",
|
|
66666
|
+
"[R, p, P] = chol(S)",
|
|
66667
|
+
"[R, p, q] = chol(S, 'vector')"
|
|
66668
|
+
],
|
|
66669
|
+
description: "Cholesky factorization with R'*R = A, reading only the upper triangle. A must be symmetric positive definite; with 2 outputs, p is 0 on success and otherwise the failing column (no error). Sparse S returns a sparse factor; with 3 outputs, P is a fill-reducing permutation with R'*R = P'*S*P."
|
|
63368
66670
|
},
|
|
63369
66671
|
rank: {
|
|
63370
66672
|
signatures: ["K = rank(A)", "K = rank(A, TOL)"],
|
|
@@ -63392,7 +66694,7 @@ var H = {
|
|
|
63392
66694
|
},
|
|
63393
66695
|
kron: {
|
|
63394
66696
|
signatures: ["K = kron(A, B)"],
|
|
63395
|
-
description: "Kronecker tensor product."
|
|
66697
|
+
description: "Kronecker tensor product. If either operand is sparse, K is sparse with nnz(A)*nnz(B) entries."
|
|
63396
66698
|
},
|
|
63397
66699
|
linsolve: {
|
|
63398
66700
|
signatures: ["X = linsolve(A, B)"],
|
|
@@ -64798,7 +68100,7 @@ function getSourceLine(getSource, file, line) {
|
|
|
64798
68100
|
}
|
|
64799
68101
|
|
|
64800
68102
|
// src/numbl-core/version.ts
|
|
64801
|
-
var NUMBL_VERSION = "0.4.
|
|
68103
|
+
var NUMBL_VERSION = "0.4.21";
|
|
64802
68104
|
|
|
64803
68105
|
// src/cli-repl.ts
|
|
64804
68106
|
import { createInterface } from "readline";
|
|
@@ -66022,9 +69324,9 @@ function analyzeLoop(stmt) {
|
|
|
66022
69324
|
};
|
|
66023
69325
|
}
|
|
66024
69326
|
function collectReadsFromSiblings(stmts, startIdx, out) {
|
|
66025
|
-
const
|
|
69327
|
+
const sink2 = /* @__PURE__ */ new Set();
|
|
66026
69328
|
for (let i = startIdx; i < stmts.length; i++) {
|
|
66027
|
-
walkStmt2(stmts[i],
|
|
69329
|
+
walkStmt2(stmts[i], sink2, out);
|
|
66028
69330
|
}
|
|
66029
69331
|
}
|
|
66030
69332
|
function walkStmts(stmts, assigned, referenced) {
|
|
@@ -66392,8 +69694,7 @@ var Registry = class {
|
|
|
66392
69694
|
const stmt = siblings[i];
|
|
66393
69695
|
const lowered = tryLower(siblings, i, ctx.interp, this.loweringCache);
|
|
66394
69696
|
if (lowered === null) {
|
|
66395
|
-
|
|
66396
|
-
return { signal: signal2 };
|
|
69697
|
+
return this.interpretFallback(ctx, stmt);
|
|
66397
69698
|
}
|
|
66398
69699
|
let bestExec = null;
|
|
66399
69700
|
let bestData = null;
|
|
@@ -66442,8 +69743,25 @@ var Registry = class {
|
|
|
66442
69743
|
}
|
|
66443
69744
|
}
|
|
66444
69745
|
}
|
|
66445
|
-
|
|
66446
|
-
|
|
69746
|
+
return this.interpretFallback(ctx, stmt);
|
|
69747
|
+
}
|
|
69748
|
+
/** Run one stmt on the AST interpreter.
|
|
69749
|
+
*
|
|
69750
|
+
* When that stmt is a loop, the interpreter is about to walk its body,
|
|
69751
|
+
* which invalidates the "an enclosing loop will capture me" assumption
|
|
69752
|
+
* behind the executors' `loopDepth` gate. `jitDeclinedLoopDepth` records
|
|
69753
|
+
* that for the duration of the body so nested loops and calls can bid for
|
|
69754
|
+
* themselves instead of running interpreted all the way down. */
|
|
69755
|
+
interpretFallback(ctx, stmt) {
|
|
69756
|
+
if (stmt.type === "For" || stmt.type === "While") {
|
|
69757
|
+
ctx.interp.jitDeclinedLoopDepth++;
|
|
69758
|
+
try {
|
|
69759
|
+
return { signal: ctx.interp.execStmt(stmt) };
|
|
69760
|
+
} finally {
|
|
69761
|
+
ctx.interp.jitDeclinedLoopDepth--;
|
|
69762
|
+
}
|
|
69763
|
+
}
|
|
69764
|
+
return { signal: ctx.interp.execStmt(stmt) };
|
|
66447
69765
|
}
|
|
66448
69766
|
runStmtCandidate(stmt, ctx, executor, data, lowered) {
|
|
66449
69767
|
const result = this.executeCandidate(ctx, executor, stmt, data, stmt);
|
|
@@ -66679,6 +69997,10 @@ __export(interpreterExec_exports, {
|
|
|
66679
69997
|
var lastDecline = null;
|
|
66680
69998
|
function recordJitDecline(d) {
|
|
66681
69999
|
lastDecline = d;
|
|
70000
|
+
if (typeof process !== "undefined" && process.env?.NUMBL_JIT_LOG) {
|
|
70001
|
+
const at = d.at ? ` [${d.at.file}@${d.at.start}]` : "";
|
|
70002
|
+
console.error(`[jit-decline] ${d.where}${at}: ${d.message}`);
|
|
70003
|
+
}
|
|
66682
70004
|
}
|
|
66683
70005
|
function getLastJitDecline() {
|
|
66684
70006
|
return lastDecline;
|
|
@@ -68667,6 +71989,7 @@ function interpretWorkspaceFunction(target, args, nargout) {
|
|
|
68667
71989
|
fn = funcDefFromStmt(stmt);
|
|
68668
71990
|
break;
|
|
68669
71991
|
}
|
|
71992
|
+
if (stmt.type !== "ClassDef" && stmt.type !== "Import") break;
|
|
68670
71993
|
}
|
|
68671
71994
|
}
|
|
68672
71995
|
}
|
|
@@ -69466,6 +72789,17 @@ var Interpreter = class {
|
|
|
69466
72789
|
* interpreter never sees them, so this gate only fires on calls
|
|
69467
72790
|
* that genuinely happen at the interpreter level inside a loop. */
|
|
69468
72791
|
loopDepth = 0;
|
|
72792
|
+
/** @internal Number of those enclosing loops that the JIT *declined*, so
|
|
72793
|
+
* the interpreter is walking their bodies statement by statement. The
|
|
72794
|
+
* `loopDepth > 0` gate above assumes an enclosing loop will be compiled
|
|
72795
|
+
* and will swallow whatever is nested inside it; when that loop was
|
|
72796
|
+
* declined instead, the assumption is false and everything below it would
|
|
72797
|
+
* run interpreted however expensive it is. The executors therefore gate on
|
|
72798
|
+
* `loopDepth > 0 && jitDeclinedLoopDepth === 0`: still no per-iteration JIT
|
|
72799
|
+
* attempts underneath a loop that is about to be compiled, but a nested
|
|
72800
|
+
* loop or call under a declined one gets its own chance. Bumped by the
|
|
72801
|
+
* registry around the interpreter fallback for a loop stmt. */
|
|
72802
|
+
jitDeclinedLoopDepth = 0;
|
|
69469
72803
|
/** @internal Number of enclosing conditional blocks (`if` / `switch` /
|
|
69470
72804
|
* `try`) whose bodies the interpreter is currently executing. Used by
|
|
69471
72805
|
* the loop classifier: when a loop is dispatched with `condBlockDepth >
|
|
@@ -70871,14 +74205,6 @@ end
|
|
|
70871
74205
|
name: "+matlab/+internal/+math/blkdiag.m",
|
|
70872
74206
|
source: "function B = blkdiag(varargin)\n B = builtin('blkdiag', varargin{:});\nend\n"
|
|
70873
74207
|
},
|
|
70874
|
-
{
|
|
70875
|
-
name: "decomposition.m",
|
|
70876
|
-
source: "classdef decomposition\n properties\n A\n checkCondition\n isIllCond\n end\n methods\n function obj = decomposition(A, varargin)\n obj.A = A;\n obj.checkCondition = true;\n for i = 1:2:length(varargin)\n if strcmpi(varargin{i}, 'CheckCondition')\n obj.checkCondition = varargin{i+1};\n end\n end\n if obj.checkCondition\n obj.isIllCond = (rcond(A) < eps);\n else\n obj.isIllCond = false;\n end\n end\n function x = mldivide(obj, b)\n x = obj.A \\ b;\n end\n end\nend\n"
|
|
70877
|
-
},
|
|
70878
|
-
{
|
|
70879
|
-
name: "isIllConditioned.m",
|
|
70880
|
-
source: "function result = isIllConditioned(dA)\n result = dA.isIllCond;\nend\n"
|
|
70881
|
-
},
|
|
70882
74208
|
{
|
|
70883
74209
|
name: "uihtml.m",
|
|
70884
74210
|
source: "classdef uihtml < handle\n %UIHTML Create an HTML UI component (numbl subset).\n % H = UIHTML('HTMLSource', HTML) renders the self-contained HTML string\n % HTML in the figure pane. An optional leading parent argument (e.g. a\n % figure) is accepted and ignored. Supported name-value options:\n % HTMLSource, Data, Position.\n %\n % H = UIHTML('HTMLSource', HTML, 'Data', X) also sends X into the page.\n % Mirroring MATLAB, X is encoded with jsonencode, parsed in the page with\n % JSON.parse, and set on the JavaScript `htmlComponent.Data` object,\n % firing any \"DataChanged\" listener registered in the page's\n % `function setup(htmlComponent)`. To update the data after construction,\n % set H.Data and call show(H) (numbl re-renders the component):\n %\n % h = uihtml('HTMLSource', html, 'Data', struct('n', 1));\n % h.Data = struct('n', 2);\n % show(h);\n %\n % numbl currently supports HTMLSource given as an HTML markup string (a\n % single self-contained document). HTML file paths and supporting files\n % are not yet supported.\n %\n % The reverse channel (page -> MATLAB) is supported for the IDE:\n % HTMLEventReceivedFcn fires when JS calls\n % htmlComponent.sendEventToMATLAB(name,data); inside the callback use\n % sendEventToHTMLSource(src,name,data) to send back to the page.\n % DataChangedFcn fires when JS sets htmlComponent.Data. Register callbacks\n % at construction (name-value) since numbl renders at construction.\n properties\n HTMLSource = ''\n Data = []\n Position = [100 100 100 100]\n HTMLEventReceivedFcn = []\n DataChangedFcn = []\n end\n methods\n function obj = uihtml(varargin)\n args = varargin;\n % Ignore an optional leading parent argument (anything that is not\n % a name-value name string).\n if numel(args) >= 1 && ~(ischar(args{1}) || isstring(args{1}))\n args = args(2:end);\n end\n for i = 1:2:numel(args) - 1\n name = args{i};\n val = args{i + 1};\n if strcmpi(name, 'HTMLSource')\n obj.HTMLSource = val;\n elseif strcmpi(name, 'Data')\n obj.Data = val;\n elseif strcmpi(name, 'Position')\n obj.Position = val;\n elseif strcmpi(name, 'HTMLEventReceivedFcn')\n obj.HTMLEventReceivedFcn = val;\n elseif strcmpi(name, 'DataChangedFcn')\n obj.DataChangedFcn = val;\n end\n end\n render(obj);\n end\n\n function show(obj)\n render(obj);\n end\n\n function render(obj)\n if isempty(obj.HTMLSource)\n return;\n end\n if isempty(obj.Data)\n id = drawuihtml(obj.HTMLSource);\n else\n id = drawuihtml(obj.HTMLSource, jsonencode(obj.Data));\n end\n if ~isempty(obj.HTMLEventReceivedFcn)\n registeruihtmlcallback(id, 'HTMLEventReceived', ...\n obj.HTMLEventReceivedFcn);\n end\n if ~isempty(obj.DataChangedFcn)\n registeruihtmlcallback(id, 'DataChanged', obj.DataChangedFcn);\n end\n end\n end\nend\n"
|
|
@@ -72651,8 +75977,12 @@ function mtoc2_cpow(a, b) {
|
|
|
72651
75977
|
}
|
|
72652
75978
|
return cexp2(mtoc2_cmul(b, clog2(a)));
|
|
72653
75979
|
}
|
|
75980
|
+
function nanOnRealAxis(z) {
|
|
75981
|
+
return z.im === 0 && Number.isNaN(z.re);
|
|
75982
|
+
}
|
|
72654
75983
|
function mtoc2_csqrt(z) {
|
|
72655
75984
|
if (z.im === 0) {
|
|
75985
|
+
if (Number.isNaN(z.re)) return { re: z.re, im: 0 };
|
|
72656
75986
|
if (z.re >= 0) return { re: Math.sqrt(z.re), im: 0 };
|
|
72657
75987
|
return { re: 0, im: Math.sqrt(-z.re) };
|
|
72658
75988
|
}
|
|
@@ -72666,14 +75996,17 @@ function mtoc2_cexp(z) {
|
|
|
72666
75996
|
return cexp2(z);
|
|
72667
75997
|
}
|
|
72668
75998
|
function mtoc2_clog(z) {
|
|
75999
|
+
if (nanOnRealAxis(z)) return { re: z.re, im: 0 };
|
|
72669
76000
|
return clog2(z);
|
|
72670
76001
|
}
|
|
72671
76002
|
function mtoc2_clog2(z) {
|
|
76003
|
+
if (nanOnRealAxis(z)) return { re: z.re, im: 0 };
|
|
72672
76004
|
const l = clog2(z);
|
|
72673
76005
|
const lg2 = Math.log(2);
|
|
72674
76006
|
return { re: l.re / lg2, im: l.im / lg2 };
|
|
72675
76007
|
}
|
|
72676
76008
|
function mtoc2_clog10(z) {
|
|
76009
|
+
if (nanOnRealAxis(z)) return { re: z.re, im: 0 };
|
|
72677
76010
|
const l = clog2(z);
|
|
72678
76011
|
const lg10 = Math.log(10);
|
|
72679
76012
|
return { re: l.re / lg10, im: l.im / lg10 };
|
|
@@ -75084,7 +78417,7 @@ var JS_SNIPPETS = {
|
|
|
75084
78417
|
"warning_fmt.js": '// JS sibling of `warning_fmt.h`. Format the message and write\n// `Warning: <msg>\\n` via `$write`. Matches numbl\n// (`runtime/specialBuiltins.ts:190` \u2014 `rt.output("Warning: " + msg + "\\n")`).\n\n\nfunction mtoc2_warning_fmt(fmt, ...args) {\n $write("Warning: " + mtoc2_sprintf_format(fmt, args) + "\\n");\n}\n\nfunction mtoc2_warning_fmt_id(_id, fmt, ...args) {\n // The id is informational \u2014 numbl threads it to lastwarn state,\n // which mtoc2 doesn\'t expose. Drop it here so the visible output\n // matches the bare form.\n $write("Warning: " + mtoc2_sprintf_format(fmt, args) + "\\n");\n}\n',
|
|
75085
78418
|
"plot_dispatch.js": '// JS sibling of `plot_dispatch.h`. Two delivery modes:\n//\n// 1. Host hook mode (numbl JIT bridge): when the host binds a\n// `$plotDispatch(name, args)` callback into the emit\'s `$h`\n// helpers, the helper forwards the raw mtoc2-shaped args to the\n// host. The host is expected to translate the args into its own\n// runtime value shape and route them into its plot pipeline\n// (numbl: `dispatchPlotBuiltin` into `rt.plotInstructions`).\n//\n// Wire-format encoding is skipped entirely in this mode \u2014 the\n// host operates in-process and consumes the same value graph the\n// emitted code already holds.\n//\n// 2. Wire-format mode (standalone AOT / viewer tee): when no host\n// hook is present, fall back to the RS-prefixed JSON record on\n// stdout that the launcher splits and forwards. Same shape the C\n// sibling emits, so a single viewer parses both backends.\n//\n// Wire shape per call (mode 2):\n// \\x1e mtoc2:plot \\t {"call":"<name>","args":[<arg>, ...]} \\n\n//\n// Arg encoding (per source-level arg):\n// number \u2192 bare numeric (non-finite \u2192 null, matching the C side\n// and JSON.stringify\'s natural behavior)\n// string \u2192 {"kind":"text","data":"<text>"}\n// char \u2192 same as string (MATLAB plot semantics don\'t distinguish)\n// tensor \u2192 {"kind":"tensor","dims":[\u2026],"data":[\u2026]} (column-major\n// flatten; non-finite as null)\n\nfunction isTensor(v) {\n return typeof v === "object" && v !== null && v.mtoc2Tag === "tensor";\n}\nfunction isChar(v) {\n return typeof v === "object" && v !== null && v.mtoc2Tag === "char";\n}\n\nfunction encodeArg(v) {\n if (typeof v === "number") {\n return Number.isFinite(v) ? v : null;\n }\n if (typeof v === "boolean") return v ? 1 : 0;\n if (typeof v === "string") return { kind: "text", data: v };\n if (isChar(v)) return { kind: "text", data: v.value };\n if (isTensor(v)) {\n const data = new Array(v.data.length);\n for (let i = 0; i < v.data.length; i++) {\n const x = v.data[i];\n data[i] = Number.isFinite(x) ? x : null;\n }\n return { kind: "tensor", dims: v.shape.slice(), data };\n }\n // Unknown shape \u2014 pass through. Type-level rejection on the\n // lowering side keeps complex/struct/class/handle out of here.\n return String(v);\n}\n\nfunction mtoc2_plot_dispatch(name, ...args) {\n if (typeof globalThis.$plotDispatch === "function") {\n globalThis.$plotDispatch(name, args);\n return;\n }\n const record = { call: name, args: args.map(encodeArg) };\n $write("\\x1emtoc2:plot\\t" + JSON.stringify(record) + "\\n");\n}\n',
|
|
75086
78419
|
"cdiv.js": "// JS sibling of `cdiv.h`. Scalar complex division matching numbl's\n// signed-Inf-on-zero-divisor behavior via Smith's algorithm. Mirrors\n// the C side so cross-runner output stays byte-for-byte.\n\nfunction mtoc2_cdiv(a, b) {\n const ar = a.re,\n ai = a.im;\n const br = b.re,\n bi = b.im;\n // Zero divisor: match the interpreter (helpers/arithmetic.ts) \u2014 0/0 is\n // NaN, a nonzero numerator yields a signed Inf per component. Smith's\n // algorithm below would otherwise produce NaN+NaNi here.\n if (br === 0 && bi === 0) {\n if (ar === 0 && ai === 0) return { re: NaN, im: 0 };\n const signedInf = x => (x > 0 ? Infinity : x < 0 ? -Infinity : 0);\n return { re: signedInf(ar), im: signedInf(ai) };\n }\n if (Math.abs(br) >= Math.abs(bi)) {\n const r = bi / br;\n const den = br + r * bi;\n return { re: (ar + ai * r) / den, im: (ai - ar * r) / den };\n }\n const r = br / bi;\n const den = bi + r * br;\n return { re: (ar * r + ai) / den, im: (ai * r - ar) / den };\n}\n",
|
|
75087
|
-
"cscalar.js": "// JS sibling of `cscalar.h`. JS has no native complex type, so each\n// helper takes and returns `{re, im}` objects. Mirrors the C\n// signatures so emitJs renders calls structurally identical to the\n// C path (just with JS objects instead of `double _Complex`).\n//\n// Division (`mtoc2_cdiv`) lives in `cdiv.js` because it needs\n// Smith's algorithm with signed-zero detection to match numbl\n// byte-for-byte.\n\nfunction mtoc2_cmake(re, im) {\n return { re, im };\n}\nfunction mtoc2_creal(z) {\n return z.re;\n}\nfunction mtoc2_cimag(z) {\n return z.im;\n}\nfunction mtoc2_cadd(a, b) {\n return { re: a.re + b.re, im: a.im + b.im };\n}\nfunction mtoc2_csub(a, b) {\n return { re: a.re - b.re, im: a.im - b.im };\n}\nfunction mtoc2_cmul(a, b) {\n return { re: a.re * b.re - a.im * b.im, im: a.re * b.im + a.im * b.re };\n}\nfunction mtoc2_cneg(z) {\n return { re: -z.re, im: -z.im };\n}\nfunction mtoc2_cconj(z) {\n return { re: z.re, im: -z.im };\n}\nfunction mtoc2_cabs(z) {\n return Math.hypot(z.re, z.im);\n}\nfunction mtoc2_cangle(z) {\n return Math.atan2(z.im, z.re);\n}\nfunction mtoc2_cnonzero(z) {\n return z.re !== 0 || z.im !== 0;\n}\nfunction mtoc2_ceq(a, b) {\n return a.re === b.re && a.im === b.im;\n}\nfunction mtoc2_cne(a, b) {\n return a.re !== b.re || a.im !== b.im;\n}\n\n// `cpow(a, b) = exp(b * log(a))`. Matches numbl / C99 `cpow` for\n// finite inputs; special zero / pole cases follow the same path\n// the C side picks (exp(NaN) = NaN, etc.).\nfunction clog(z) {\n // Normalize a -0 real part to +0 so log(-0) (a real -0) gives\n // -Inf + 0i, not -Inf + \u03C0i \u2014 MATLAB / C99 treat -0 as 0, not as an\n // approach-from-below negative. atan2's -0 second arg only changes the\n // result when the first arg is also 0, so this affects nothing else.\n const reAngle = z.re === 0 ? 0 : z.re;\n return {\n re: Math.log(Math.hypot(z.re, z.im)),\n im: Math.atan2(z.im, reAngle),\n };\n}\nfunction cexp(z) {\n const m = Math.exp(z.re);\n // Real-valued input (im === 0): the imaginary lane is m*sin(0) = 0, but\n // when m overflows to Inf that becomes Inf*0 = NaN. Return a clean 0\n // (matches the interpreter's real exp and C99 cexp).\n if (z.im === 0) return { re: m, im: 0 };\n return { re: m * Math.cos(z.im), im: m * Math.sin(z.im) };\n}\nfunction mtoc2_cpow(a, b) {\n // Zero base: match the interpreter's complexPow (helpers/arithmetic.ts)\n // \u2014 0^0 = 1, a positive real part of the exponent gives 0 (regardless\n // of the imaginary part), and anything else gives Inf+0i. The old\n // guard required b.im===0 for the zero case and otherwise returned\n // NaN+NaNi.\n if (a.re === 0 && a.im === 0) {\n if (b.re === 0 && b.im === 0) return { re: 1, im: 0 };\n if (b.re > 0) return { re: 0, im: 0 };\n return { re: Infinity, im: 0 };\n }\n return cexp(mtoc2_cmul(b, clog(a)));\n}\n\n// Unary math.\nfunction mtoc2_csqrt(z) {\n // Pure-real input: compute directly. Smith's formula below suffers\n // catastrophic cancellation/overflow when z.im === 0 \u2014 e.g.\n // sqrt(-Inf) \u2192 sqrt((Inf + -Inf)/2) = sqrt(NaN) = NaN, and\n // sqrt(-1e308) \u2192 sqrt((1e308 - -1e308)/2) overflows to Inf instead of\n // 1e154. Mirror the interpreter's complexSqrt (math.ts) and C's libm\n // csqrt, both of which special-case the real axis.\n if (z.im === 0) {\n if (z.re >= 0) return { re: Math.sqrt(z.re), im: 0 };\n return { re: 0, im: Math.sqrt(-z.re) };\n }\n // Smith's stable formula for hypot * sign.\n const r = Math.hypot(z.re, z.im);\n if (r === 0) return { re: 0, im: 0 };\n const re = Math.sqrt((r + z.re) / 2);\n const im = (z.im >= 0 ? 1 : -1) * Math.sqrt((r - z.re) / 2);\n return { re, im };\n}\nfunction mtoc2_cexp(z) {\n return cexp(z);\n}\nfunction mtoc2_clog(z) {\n return clog(z);\n}\nfunction mtoc2_clog2(z) {\n const l = clog(z);\n const lg2 = Math.log(2);\n return { re: l.re / lg2, im: l.im / lg2 };\n}\nfunction mtoc2_clog10(z) {\n const l = clog(z);\n const lg10 = Math.log(10);\n return { re: l.re / lg10, im: l.im / lg10 };\n}\nfunction mtoc2_csin(z) {\n // Guard 0*Inf=NaN on the imaginary axis: for a pure-imaginary input\n // (sin(z.re)===0), the real lane is 0 and the imaginary lane is\n // \xB1sinh(im); cosh/sinh overflow to Inf for large |im|, and 0*Inf would\n // poison the result. C99 csin special-cases this \u2014 match it.\n const sr = Math.sin(z.re);\n const cr = Math.cos(z.re);\n return {\n re: sr === 0 ? 0 : sr * Math.cosh(z.im),\n im: cr === 0 ? 0 : cr * Math.sinh(z.im),\n };\n}\nfunction mtoc2_ccos(z) {\n const cr = Math.cos(z.re);\n const sr = Math.sin(z.re);\n return {\n re: cr === 0 ? 0 : cr * Math.cosh(z.im),\n im: sr === 0 ? 0 : -sr * Math.sinh(z.im),\n };\n}\nfunction mtoc2_ctan(z) {\n // Double-angle form, matching the interpreter (interpreter/builtins/\n // math.ts) and C99 ctan. Computing sin(z)/cos(z) with a |cos|^2\n // denominator loses the (tiny but nonzero) real part and overflows\n // for large imaginary parts \u2014 e.g. tan(1+200i) collapsed to 1i.\n const denom = Math.cos(2 * z.re) + Math.cosh(2 * z.im);\n return { re: Math.sin(2 * z.re) / denom, im: Math.sinh(2 * z.im) / denom };\n}\nfunction mtoc2_catan(z) {\n // Real-valued input (im === 0): atan is a clean real function. The\n // complex formula leaves a spurious \xB11e-17i residue (and NaN+NaNi once\n // 1\xB1iz overflows, e.g. atan(1e300)). Take the real path.\n if (z.im === 0) return { re: Math.atan(z.re), im: 0 };\n // atan(z) = (i/2)\xB7log((1 \u2212 iz)/(1 + iz)) \u2014 MATLAB's branch (atan(2i) =\n // \u22121.5708 + 0.5493i). The C runtime overrides its libc catan (which\n // uses the opposite +\u03C0/2 Annex-G branch) to match this.\n const iz = { re: -z.im, im: z.re }; // i*z\n const num = { re: 1 - iz.re, im: -iz.im }; // 1 - iz\n const denom = { re: 1 + iz.re, im: iz.im }; // 1 + iz\n const dd = denom.re * denom.re + denom.im * denom.im;\n const q = {\n re: (num.re * denom.re + num.im * denom.im) / dd,\n im: (num.im * denom.re - num.re * denom.im) / dd,\n };\n const l = clog(q);\n return { re: -l.im / 2, im: l.re / 2 };\n}\n// Hyperbolic sinh/cosh/tanh \u2014 byte-for-byte with the interpreter's\n// complex formulas (interpreter/builtins/math.ts). Real-valued input\n// (im === 0) falls out cleanly: cos(0)=1, sin(0)=0, so the imaginary\n// lane is exactly 0.\nfunction mtoc2_csinh(z) {\n return {\n re: Math.sinh(z.re) * Math.cos(z.im),\n im: Math.cosh(z.re) * Math.sin(z.im),\n };\n}\nfunction mtoc2_ccosh(z) {\n return {\n re: Math.cosh(z.re) * Math.cos(z.im),\n im: Math.sinh(z.re) * Math.sin(z.im),\n };\n}\nfunction mtoc2_ctanh(z) {\n const denom = Math.cosh(2 * z.re) + Math.cos(2 * z.im);\n return { re: Math.sinh(2 * z.re) / denom, im: Math.sin(2 * z.im) / denom };\n}\nfunction mtoc2_cfloor(z) {\n return { re: Math.floor(z.re), im: Math.floor(z.im) };\n}\nfunction mtoc2_cceil(z) {\n return { re: Math.ceil(z.re), im: Math.ceil(z.im) };\n}\nfunction mtoc2_cround(z) {\n // MATLAB rounds each component half-away-from-zero.\n const half = x => Math.sign(x) * Math.round(Math.abs(x));\n return { re: half(z.re), im: half(z.im) };\n}\nfunction mtoc2_cfix(z) {\n return { re: Math.trunc(z.re), im: Math.trunc(z.im) };\n}\nfunction mtoc2_csign(z) {\n if (z.re === 0 && z.im === 0) return { re: 0, im: 0 };\n const m = Math.hypot(z.re, z.im);\n return { re: z.re / m, im: z.im / m };\n}\n",
|
|
78420
|
+
"cscalar.js": "// JS sibling of `cscalar.h`. JS has no native complex type, so each\n// helper takes and returns `{re, im}` objects. Mirrors the C\n// signatures so emitJs renders calls structurally identical to the\n// C path (just with JS objects instead of `double _Complex`).\n//\n// Division (`mtoc2_cdiv`) lives in `cdiv.js` because it needs\n// Smith's algorithm with signed-zero detection to match numbl\n// byte-for-byte.\n\nfunction mtoc2_cmake(re, im) {\n return { re, im };\n}\nfunction mtoc2_creal(z) {\n return z.re;\n}\nfunction mtoc2_cimag(z) {\n return z.im;\n}\nfunction mtoc2_cadd(a, b) {\n return { re: a.re + b.re, im: a.im + b.im };\n}\nfunction mtoc2_csub(a, b) {\n return { re: a.re - b.re, im: a.im - b.im };\n}\nfunction mtoc2_cmul(a, b) {\n return { re: a.re * b.re - a.im * b.im, im: a.re * b.im + a.im * b.re };\n}\nfunction mtoc2_cneg(z) {\n return { re: -z.re, im: -z.im };\n}\nfunction mtoc2_cconj(z) {\n return { re: z.re, im: -z.im };\n}\nfunction mtoc2_cabs(z) {\n return Math.hypot(z.re, z.im);\n}\nfunction mtoc2_cangle(z) {\n return Math.atan2(z.im, z.re);\n}\nfunction mtoc2_cnonzero(z) {\n return z.re !== 0 || z.im !== 0;\n}\nfunction mtoc2_ceq(a, b) {\n return a.re === b.re && a.im === b.im;\n}\nfunction mtoc2_cne(a, b) {\n return a.re !== b.re || a.im !== b.im;\n}\n\n// `cpow(a, b) = exp(b * log(a))`. Matches numbl / C99 `cpow` for\n// finite inputs; special zero / pole cases follow the same path\n// the C side picks (exp(NaN) = NaN, etc.).\nfunction clog(z) {\n // Normalize a -0 real part to +0 so log(-0) (a real -0) gives\n // -Inf + 0i, not -Inf + \u03C0i \u2014 MATLAB / C99 treat -0 as 0, not as an\n // approach-from-below negative. atan2's -0 second arg only changes the\n // result when the first arg is also 0, so this affects nothing else.\n const reAngle = z.re === 0 ? 0 : z.re;\n return {\n re: Math.log(Math.hypot(z.re, z.im)),\n im: Math.atan2(z.im, reAngle),\n };\n}\nfunction cexp(z) {\n const m = Math.exp(z.re);\n // Real-valued input (im === 0): the imaginary lane is m*sin(0) = 0, but\n // when m overflows to Inf that becomes Inf*0 = NaN. Return a clean 0\n // (matches the interpreter's real exp and C99 cexp).\n if (z.im === 0) return { re: m, im: 0 };\n return { re: m * Math.cos(z.im), im: m * Math.sin(z.im) };\n}\nfunction mtoc2_cpow(a, b) {\n // Zero base: match the interpreter's complexPow (helpers/arithmetic.ts)\n // \u2014 0^0 = 1, a positive real part of the exponent gives 0 (regardless\n // of the imaginary part), and anything else gives Inf+0i. The old\n // guard required b.im===0 for the zero case and otherwise returned\n // NaN+NaNi.\n if (a.re === 0 && a.im === 0) {\n if (b.re === 0 && b.im === 0) return { re: 1, im: 0 };\n if (b.re > 0) return { re: 0, im: 0 };\n return { re: Infinity, im: 0 };\n }\n return cexp(mtoc2_cmul(b, clog(a)));\n}\n\n/** True when `z` is a NaN sitting on the real axis.\n *\n * These helpers are reached both from genuinely complex arithmetic and from\n * the *lift* the JIT performs on a real argument whose sign it cannot prove\n * (`sqrt(x)`, `log(x)`). MATLAB's sqrt(NaN) and log(NaN) are a real NaN, so a\n * lifted NaN must come back as NaN + 0i and not, say, 0 + NaN i: the lift is\n * a compilation detail and must not change what `real`, `isreal`,\n * `jsonencode` or a printed value say. */\nfunction nanOnRealAxis(z) {\n return z.im === 0 && Number.isNaN(z.re);\n}\n\n// Unary math.\nfunction mtoc2_csqrt(z) {\n // Pure-real input: compute directly. Smith's formula below suffers\n // catastrophic cancellation/overflow when z.im === 0 \u2014 e.g.\n // sqrt(-Inf) \u2192 sqrt((Inf + -Inf)/2) = sqrt(NaN) = NaN, and\n // sqrt(-1e308) \u2192 sqrt((1e308 - -1e308)/2) overflows to Inf instead of\n // 1e154. Mirror the interpreter's complexSqrt (math.ts) and C's libm\n // csqrt, both of which special-case the real axis.\n if (z.im === 0) {\n if (Number.isNaN(z.re)) return { re: z.re, im: 0 };\n if (z.re >= 0) return { re: Math.sqrt(z.re), im: 0 };\n return { re: 0, im: Math.sqrt(-z.re) };\n }\n // Smith's stable formula for hypot * sign.\n const r = Math.hypot(z.re, z.im);\n if (r === 0) return { re: 0, im: 0 };\n const re = Math.sqrt((r + z.re) / 2);\n const im = (z.im >= 0 ? 1 : -1) * Math.sqrt((r - z.re) / 2);\n return { re, im };\n}\nfunction mtoc2_cexp(z) {\n return cexp(z);\n}\nfunction mtoc2_clog(z) {\n if (nanOnRealAxis(z)) return { re: z.re, im: 0 };\n return clog(z);\n}\nfunction mtoc2_clog2(z) {\n if (nanOnRealAxis(z)) return { re: z.re, im: 0 };\n const l = clog(z);\n const lg2 = Math.log(2);\n return { re: l.re / lg2, im: l.im / lg2 };\n}\nfunction mtoc2_clog10(z) {\n if (nanOnRealAxis(z)) return { re: z.re, im: 0 };\n const l = clog(z);\n const lg10 = Math.log(10);\n return { re: l.re / lg10, im: l.im / lg10 };\n}\nfunction mtoc2_csin(z) {\n // Guard 0*Inf=NaN on the imaginary axis: for a pure-imaginary input\n // (sin(z.re)===0), the real lane is 0 and the imaginary lane is\n // \xB1sinh(im); cosh/sinh overflow to Inf for large |im|, and 0*Inf would\n // poison the result. C99 csin special-cases this \u2014 match it.\n const sr = Math.sin(z.re);\n const cr = Math.cos(z.re);\n return {\n re: sr === 0 ? 0 : sr * Math.cosh(z.im),\n im: cr === 0 ? 0 : cr * Math.sinh(z.im),\n };\n}\nfunction mtoc2_ccos(z) {\n const cr = Math.cos(z.re);\n const sr = Math.sin(z.re);\n return {\n re: cr === 0 ? 0 : cr * Math.cosh(z.im),\n im: sr === 0 ? 0 : -sr * Math.sinh(z.im),\n };\n}\nfunction mtoc2_ctan(z) {\n // Double-angle form, matching the interpreter (interpreter/builtins/\n // math.ts) and C99 ctan. Computing sin(z)/cos(z) with a |cos|^2\n // denominator loses the (tiny but nonzero) real part and overflows\n // for large imaginary parts \u2014 e.g. tan(1+200i) collapsed to 1i.\n const denom = Math.cos(2 * z.re) + Math.cosh(2 * z.im);\n return { re: Math.sin(2 * z.re) / denom, im: Math.sinh(2 * z.im) / denom };\n}\nfunction mtoc2_catan(z) {\n // Real-valued input (im === 0): atan is a clean real function. The\n // complex formula leaves a spurious \xB11e-17i residue (and NaN+NaNi once\n // 1\xB1iz overflows, e.g. atan(1e300)). Take the real path.\n if (z.im === 0) return { re: Math.atan(z.re), im: 0 };\n // atan(z) = (i/2)\xB7log((1 \u2212 iz)/(1 + iz)) \u2014 MATLAB's branch (atan(2i) =\n // \u22121.5708 + 0.5493i). The C runtime overrides its libc catan (which\n // uses the opposite +\u03C0/2 Annex-G branch) to match this.\n const iz = { re: -z.im, im: z.re }; // i*z\n const num = { re: 1 - iz.re, im: -iz.im }; // 1 - iz\n const denom = { re: 1 + iz.re, im: iz.im }; // 1 + iz\n const dd = denom.re * denom.re + denom.im * denom.im;\n const q = {\n re: (num.re * denom.re + num.im * denom.im) / dd,\n im: (num.im * denom.re - num.re * denom.im) / dd,\n };\n const l = clog(q);\n return { re: -l.im / 2, im: l.re / 2 };\n}\n// Hyperbolic sinh/cosh/tanh \u2014 byte-for-byte with the interpreter's\n// complex formulas (interpreter/builtins/math.ts). Real-valued input\n// (im === 0) falls out cleanly: cos(0)=1, sin(0)=0, so the imaginary\n// lane is exactly 0.\nfunction mtoc2_csinh(z) {\n return {\n re: Math.sinh(z.re) * Math.cos(z.im),\n im: Math.cosh(z.re) * Math.sin(z.im),\n };\n}\nfunction mtoc2_ccosh(z) {\n return {\n re: Math.cosh(z.re) * Math.cos(z.im),\n im: Math.sinh(z.re) * Math.sin(z.im),\n };\n}\nfunction mtoc2_ctanh(z) {\n const denom = Math.cosh(2 * z.re) + Math.cos(2 * z.im);\n return { re: Math.sinh(2 * z.re) / denom, im: Math.sin(2 * z.im) / denom };\n}\nfunction mtoc2_cfloor(z) {\n return { re: Math.floor(z.re), im: Math.floor(z.im) };\n}\nfunction mtoc2_cceil(z) {\n return { re: Math.ceil(z.re), im: Math.ceil(z.im) };\n}\nfunction mtoc2_cround(z) {\n // MATLAB rounds each component half-away-from-zero.\n const half = x => Math.sign(x) * Math.round(Math.abs(x));\n return { re: half(z.re), im: half(z.im) };\n}\nfunction mtoc2_cfix(z) {\n return { re: Math.trunc(z.re), im: Math.trunc(z.im) };\n}\nfunction mtoc2_csign(z) {\n if (z.re === 0 && z.im === 0) return { re: 0, im: 0 };\n const m = Math.hypot(z.re, z.im);\n return { re: z.re / m, im: z.im / m };\n}\n",
|
|
75088
78421
|
"deep_clone.js": '/* Deep-clone an owned-typed runtime value so a subsequent member /\n * indexed write through one alias doesn\'t leak to others. Mirrors\n * the c-aot per-typedef `_copy` protocol: every Var-RHS Assign /\n * MemberLoad-RHS Assign / function-call arg of an owned type is\n * wrapped through this helper at emit time, so JS-side aliasing\n * stops at the assignment boundary.\n *\n * Recognises the runtime shapes the rest of mtoc2 emits:\n * - RuntimeTensor (`{mtoc2Tag:"tensor", shape, data, imag?, isLogical?}`)\n * - RuntimeChar (`{mtoc2Tag:"char", value}`)\n * - struct / class / handle / handle-capture objects \u2014 plain JS\n * objects, optionally with a non-enumerable `mtoc2Class` tag\n * (class instances) that must survive the clone for method\n * dispatch\n *\n * Primitives (numbers, booleans, strings, null/undefined) flow\n * through unchanged \u2014 they\'re already value-typed in JS.\n */\n\nfunction mtoc2_deep_clone(v) {\n if (v === null || typeof v !== "object") return v;\n if (v.mtoc2Tag === "tensor") {\n const out = {\n mtoc2Tag: "tensor",\n shape: v.shape.slice(),\n data: v.data.slice(),\n };\n if (v.imag !== undefined) out.imag = v.imag.slice();\n if (v.isLogical) out.isLogical = true;\n return out;\n }\n if (v.mtoc2Tag === "char") {\n return { mtoc2Tag: "char", value: v.value };\n }\n if (v.mtoc2Tag === "cell") {\n return {\n mtoc2Tag: "cell",\n shape: v.shape.slice(),\n data: v.data.map(mtoc2_deep_clone),\n };\n }\n if (v.mtoc2Handle === true) {\n // Function handle \u2014 captures are deep-cloned so a later write\n // through one alias doesn\'t bleed into another handle\'s frozen\n // capture snapshot.\n if (v.kind === "named") {\n return { mtoc2Handle: true, kind: "named", name: v.name };\n }\n const captures = {};\n for (const k of Object.keys(v.captures)) {\n captures[k] = mtoc2_deep_clone(v.captures[k]);\n }\n return {\n mtoc2Handle: true,\n kind: "anon",\n params: v.params,\n body: v.body,\n captures,\n };\n }\n // Plain struct / class instance: walk enumerable fields, then\n // restore the non-enumerable `mtoc2Class` tag if it was present.\n const out = {};\n for (const k of Object.keys(v)) {\n out[k] = mtoc2_deep_clone(v[k]);\n }\n const tag = Object.getOwnPropertyDescriptor(v, "mtoc2Class");\n if (tag !== undefined) {\n Object.defineProperty(out, "mtoc2Class", {\n value: tag.value,\n enumerable: false,\n writable: false,\n });\n }\n return out;\n}\n',
|
|
75089
78422
|
"isequal.js": "// JS sibling of `isequal.h`. Same real-numeric equality semantics for\n// the js-aot backend. Tensors carry `shape` / `data` (the JS analogue\n// of the C struct's `dims` / `real`).\n\nfunction mtoc2_isequal_tt(a, b) {\n if (a.shape.length !== b.shape.length) return 0;\n let n = 1;\n for (let i = 0; i < a.shape.length; i++) {\n if (a.shape[i] !== b.shape[i]) return 0;\n n *= a.shape[i];\n }\n for (let i = 0; i < n; i++) {\n if (a.data[i] !== b.data[i]) return 0;\n }\n return 1;\n}\n\nfunction mtoc2_isequal_st(s, t) {\n let n = 1;\n for (let i = 0; i < t.shape.length; i++) n *= t.shape[i];\n if (n !== 1) return 0;\n return t.data[0] === s ? 1 : 0;\n}\n",
|
|
75090
78423
|
"tictoc.js": '// JS sibling of `tictoc.h`. Same "one global timer" semantics. Uses\n// `performance.now()` to match numbl\'s wall-clock source; the output\n// format string mirrors numbl\'s `"Elapsed time is %.6f seconds.\\n"`\n// so the cross-runner\'s masking regex still treats both runtimes as\n// equivalent.\n//\n// Module-scope state for the shared `tic` slot. The codegen path\n// inlines this declaration alongside the helpers; the interpreter\n// imports them as ES exports and the same module-scope `let` is the\n// canonical slot.\n\nlet mtoc2_tic_seconds = 0;\n\nfunction mtoc2_now_seconds() {\n // `performance.now()` returns milliseconds since some monotonic\n // epoch; divide for seconds. (Node and browsers both supply it on\n // `globalThis.performance` as of recent versions.)\n return performance.now() / 1000;\n}\n\nfunction mtoc2_tic() {\n mtoc2_tic_seconds = mtoc2_now_seconds();\n return mtoc2_tic_seconds;\n}\n\nfunction mtoc2_toc() {\n return mtoc2_now_seconds() - mtoc2_tic_seconds;\n}\n\nfunction mtoc2_toc_handle(start_seconds) {\n return mtoc2_now_seconds() - start_seconds;\n}\n\nfunction mtoc2_toc_print() {\n const elapsed = mtoc2_toc();\n $write(`Elapsed time is ${elapsed.toFixed(6)} seconds.\\n`);\n}\n\nfunction mtoc2_toc_handle_print(start_seconds) {\n const elapsed = mtoc2_now_seconds() - start_seconds;\n $write(`Elapsed time is ${elapsed.toFixed(6)} seconds.\\n`);\n}\n',
|
|
@@ -80190,7 +83523,7 @@ function cCos(z) {
|
|
|
80190
83523
|
im: -Math.sin(z.re) * Math.sinh(z.im)
|
|
80191
83524
|
};
|
|
80192
83525
|
}
|
|
80193
|
-
function
|
|
83526
|
+
function cdiv3(a, b) {
|
|
80194
83527
|
if (Math.abs(b.re) >= Math.abs(b.im)) {
|
|
80195
83528
|
const r2 = b.im / b.re;
|
|
80196
83529
|
const den2 = b.re + r2 * b.im;
|
|
@@ -80201,7 +83534,7 @@ function cdiv2(a, b) {
|
|
|
80201
83534
|
return { re: (a.re * r + a.im) / den, im: (a.im * r - a.re) / den };
|
|
80202
83535
|
}
|
|
80203
83536
|
function cTan(z) {
|
|
80204
|
-
return
|
|
83537
|
+
return cdiv3(cSin(z), cCos(z));
|
|
80205
83538
|
}
|
|
80206
83539
|
function cSinh(z) {
|
|
80207
83540
|
return {
|
|
@@ -80223,7 +83556,7 @@ function cAtan(z) {
|
|
|
80223
83556
|
const iz = { re: -z.im, im: z.re };
|
|
80224
83557
|
const num = { re: 1 - iz.re, im: -iz.im };
|
|
80225
83558
|
const den = { re: 1 + iz.re, im: iz.im };
|
|
80226
|
-
const q =
|
|
83559
|
+
const q = cdiv3(num, den);
|
|
80227
83560
|
const l = cLog(q);
|
|
80228
83561
|
return { re: -l.im / 2, im: l.re / 2 };
|
|
80229
83562
|
}
|
|
@@ -87933,6 +91266,24 @@ function lowerMultiAssign(s) {
|
|
|
87933
91266
|
);
|
|
87934
91267
|
}
|
|
87935
91268
|
}
|
|
91269
|
+
if (target?.kind === "mtoc2UserFunction") {
|
|
91270
|
+
const userBuiltin = this.workspace.getUserBuiltin(target.name);
|
|
91271
|
+
if (!userBuiltin) {
|
|
91272
|
+
throw new UnsupportedConstruct(
|
|
91273
|
+
`internal: workspace resolved '${callName}' to a .mtoc2.js function but no Builtin is loaded`,
|
|
91274
|
+
s.span
|
|
91275
|
+
);
|
|
91276
|
+
}
|
|
91277
|
+
return buildBuiltinMultiAssign.call(
|
|
91278
|
+
this,
|
|
91279
|
+
callName,
|
|
91280
|
+
userBuiltin,
|
|
91281
|
+
anfArgs,
|
|
91282
|
+
argTypes,
|
|
91283
|
+
argHoists,
|
|
91284
|
+
s
|
|
91285
|
+
);
|
|
91286
|
+
}
|
|
87936
91287
|
if (target?.kind !== "userFunction") {
|
|
87937
91288
|
throw new UnsupportedConstruct(
|
|
87938
91289
|
`multi-assign of '${callName}': only user-defined functions can appear on the right of '[...] = ...' (or as a bare multi-output statement)`,
|
|
@@ -88468,23 +91819,6 @@ function lowerIndexSliceStore(lvalue, exprAst, span) {
|
|
|
88468
91819
|
}
|
|
88469
91820
|
}
|
|
88470
91821
|
}
|
|
88471
|
-
if (!isSingleSlot && r.baseTy.kind === "Numeric") {
|
|
88472
|
-
for (let i = 0; i < slots.length; i++) {
|
|
88473
|
-
const slot = slots[i];
|
|
88474
|
-
if (slot.kind !== "Scalar") continue;
|
|
88475
|
-
const dim = r.baseTy.dims[i];
|
|
88476
|
-
const t = slot.expr.ty;
|
|
88477
|
-
const dimKnown = dim !== void 0 && dim.kind === "exact";
|
|
88478
|
-
const valKnown = t.kind === "Numeric" && typeof t.exact === "number";
|
|
88479
|
-
const provablyInBounds = dimKnown && valKnown && Math.round(t.exact) >= 1 && Math.round(t.exact) <= dim.value;
|
|
88480
|
-
if (!provablyInBounds) {
|
|
88481
|
-
throw new UnsupportedConstruct(
|
|
88482
|
-
`indexed write to '${displayName}' at axis ${i + 1}: cannot statically prove the index stays within the tensor's bounds; would auto-grow / OOB in MATLAB, but auto-grow is not modeled in the JIT`,
|
|
88483
|
-
slot.span
|
|
88484
|
-
);
|
|
88485
|
-
}
|
|
88486
|
-
}
|
|
88487
|
-
}
|
|
88488
91822
|
const rawRhs = this.lowerExpr(exprAst);
|
|
88489
91823
|
if (!isNumeric2(rawRhs.ty)) {
|
|
88490
91824
|
throw new TypeError2(
|
|
@@ -88800,6 +92134,8 @@ var Lowerer = class {
|
|
|
88800
92134
|
return lowerMultiAssign.call(this, s);
|
|
88801
92135
|
case "If":
|
|
88802
92136
|
return this.lowerIf(s);
|
|
92137
|
+
case "Switch":
|
|
92138
|
+
return this.lowerSwitch(s);
|
|
88803
92139
|
case "While":
|
|
88804
92140
|
return this.lowerWhile(s);
|
|
88805
92141
|
case "For":
|
|
@@ -88891,6 +92227,23 @@ var Lowerer = class {
|
|
|
88891
92227
|
return entries;
|
|
88892
92228
|
}
|
|
88893
92229
|
lowerExprStmt(s) {
|
|
92230
|
+
if (this.env.get("tic") === void 0 && !this.workspace.isClass("tic")) {
|
|
92231
|
+
const bareTic = s.expr.type === "Ident" && s.expr.name === "tic" || s.expr.type === "FuncCall" && s.expr.name === "tic" && s.expr.args.length === 0;
|
|
92232
|
+
if (bareTic) {
|
|
92233
|
+
return {
|
|
92234
|
+
kind: "ExprStmt",
|
|
92235
|
+
expr: {
|
|
92236
|
+
kind: "Call",
|
|
92237
|
+
cName: "mtoc2_tic",
|
|
92238
|
+
name: "tic",
|
|
92239
|
+
args: [],
|
|
92240
|
+
ty: VOID,
|
|
92241
|
+
span: s.expr.span
|
|
92242
|
+
},
|
|
92243
|
+
span: s.span
|
|
92244
|
+
};
|
|
92245
|
+
}
|
|
92246
|
+
}
|
|
88894
92247
|
if (this.env.get("toc") === void 0 && !this.workspace.isClass("toc")) {
|
|
88895
92248
|
if (s.expr.type === "Ident" && s.expr.name === "toc") {
|
|
88896
92249
|
return {
|
|
@@ -89497,6 +92850,125 @@ var Lowerer = class {
|
|
|
89497
92850
|
}
|
|
89498
92851
|
];
|
|
89499
92852
|
}
|
|
92853
|
+
/** MATLAB `switch` lowered to the equivalent if/elseif chain.
|
|
92854
|
+
*
|
|
92855
|
+
* The subject is evaluated once — hoisted to a temp unless it is already a
|
|
92856
|
+
* plain variable — and each case label becomes an equality test against it:
|
|
92857
|
+
* `strcmp` for text, `==` for numbers. A `case {a, b}` list is the OR of
|
|
92858
|
+
* the individual tests. Everything after that is `lowerIf`'s problem, which
|
|
92859
|
+
* means switch inherits its branch-env merging and cond folding.
|
|
92860
|
+
*
|
|
92861
|
+
* Declined (leaving the unit to the interpreter, as before this existed):
|
|
92862
|
+
* a subject that is neither a scalar number nor text, a label whose kind
|
|
92863
|
+
* does not match the subject's, and an empty `case {}`.
|
|
92864
|
+
*/
|
|
92865
|
+
lowerSwitch(s) {
|
|
92866
|
+
const span = s.span;
|
|
92867
|
+
const pre = [];
|
|
92868
|
+
let subject = s.expr;
|
|
92869
|
+
if (!(s.expr.type === "Ident" && this.env.has(s.expr.name))) {
|
|
92870
|
+
const tmp = this.freshTempName();
|
|
92871
|
+
const assign = {
|
|
92872
|
+
type: "Assign",
|
|
92873
|
+
name: tmp,
|
|
92874
|
+
expr: s.expr,
|
|
92875
|
+
suppressed: true,
|
|
92876
|
+
span
|
|
92877
|
+
};
|
|
92878
|
+
const lowered = this.lowerStmt(assign);
|
|
92879
|
+
if (lowered !== null) {
|
|
92880
|
+
if (Array.isArray(lowered)) pre.push(...lowered);
|
|
92881
|
+
else pre.push(lowered);
|
|
92882
|
+
}
|
|
92883
|
+
subject = { type: "Ident", name: tmp, span };
|
|
92884
|
+
}
|
|
92885
|
+
const subjTy = this.env.get(subject.name)?.ty;
|
|
92886
|
+
if (subjTy === void 0) {
|
|
92887
|
+
throw new UnsupportedConstruct(
|
|
92888
|
+
"switch subject is not a value the JIT can type",
|
|
92889
|
+
span
|
|
92890
|
+
);
|
|
92891
|
+
}
|
|
92892
|
+
const subjIsText = subjTy.kind === "Char" || subjTy.kind === "String";
|
|
92893
|
+
const subjIsNum = isScalarRealNumeric(subjTy) || subjTy.kind === "Numeric";
|
|
92894
|
+
if (!subjIsText && !(subjIsNum && isScalar(subjTy))) {
|
|
92895
|
+
throw new UnsupportedConstruct(
|
|
92896
|
+
`switch on a ${typeToString(subjTy)} subject is not supported (scalar numeric or text only)`,
|
|
92897
|
+
span
|
|
92898
|
+
);
|
|
92899
|
+
}
|
|
92900
|
+
const labelIsText = (label) => {
|
|
92901
|
+
if (label.type === "Char" || label.type === "String") return true;
|
|
92902
|
+
if (label.type === "Ident") {
|
|
92903
|
+
const t = this.env.get(label.name)?.ty;
|
|
92904
|
+
return t !== void 0 && (t.kind === "Char" || t.kind === "String");
|
|
92905
|
+
}
|
|
92906
|
+
return false;
|
|
92907
|
+
};
|
|
92908
|
+
const labelCond = (label) => {
|
|
92909
|
+
if (subjIsText) {
|
|
92910
|
+
if (!labelIsText(label)) {
|
|
92911
|
+
throw new UnsupportedConstruct(
|
|
92912
|
+
"switch on text with a non-text case label is not supported",
|
|
92913
|
+
label.span
|
|
92914
|
+
);
|
|
92915
|
+
}
|
|
92916
|
+
return {
|
|
92917
|
+
type: "FuncCall",
|
|
92918
|
+
name: "strcmp",
|
|
92919
|
+
args: [subject, label],
|
|
92920
|
+
span: label.span
|
|
92921
|
+
};
|
|
92922
|
+
}
|
|
92923
|
+
if (labelIsText(label)) {
|
|
92924
|
+
throw new UnsupportedConstruct(
|
|
92925
|
+
"switch on a number with a text case label is not supported",
|
|
92926
|
+
label.span
|
|
92927
|
+
);
|
|
92928
|
+
}
|
|
92929
|
+
return {
|
|
92930
|
+
type: "Binary",
|
|
92931
|
+
left: subject,
|
|
92932
|
+
op: "Equal" /* Equal */,
|
|
92933
|
+
right: label,
|
|
92934
|
+
span: label.span
|
|
92935
|
+
};
|
|
92936
|
+
};
|
|
92937
|
+
const caseCond = (value) => {
|
|
92938
|
+
if (value.type !== "Cell") return labelCond(value);
|
|
92939
|
+
const items = value.rows.flat();
|
|
92940
|
+
if (items.length === 0) {
|
|
92941
|
+
throw new UnsupportedConstruct(
|
|
92942
|
+
"switch with an empty case list is not supported",
|
|
92943
|
+
value.span
|
|
92944
|
+
);
|
|
92945
|
+
}
|
|
92946
|
+
return items.map(labelCond).reduce((acc, c) => ({
|
|
92947
|
+
type: "Binary",
|
|
92948
|
+
left: acc,
|
|
92949
|
+
op: "OrOr" /* OrOr */,
|
|
92950
|
+
right: c,
|
|
92951
|
+
span: value.span
|
|
92952
|
+
}));
|
|
92953
|
+
};
|
|
92954
|
+
if (s.cases.length === 0) {
|
|
92955
|
+
const body = s.otherwise ? this.lowerStmts(s.otherwise) : [];
|
|
92956
|
+
return [...pre, ...body];
|
|
92957
|
+
}
|
|
92958
|
+
const chain = {
|
|
92959
|
+
type: "If",
|
|
92960
|
+
cond: caseCond(s.cases[0].value),
|
|
92961
|
+
thenBody: s.cases[0].body,
|
|
92962
|
+
elseifBlocks: s.cases.slice(1).map((c) => ({
|
|
92963
|
+
cond: caseCond(c.value),
|
|
92964
|
+
body: c.body
|
|
92965
|
+
})),
|
|
92966
|
+
elseBody: s.otherwise,
|
|
92967
|
+
span
|
|
92968
|
+
};
|
|
92969
|
+
const ir = this.lowerIf(chain);
|
|
92970
|
+
return [...pre, ...Array.isArray(ir) ? ir : [ir]];
|
|
92971
|
+
}
|
|
89500
92972
|
lowerWhile(s) {
|
|
89501
92973
|
const envBefore = new Map(this.env);
|
|
89502
92974
|
stripExactFromEnv(this.env, collectAssignedNames(s.body));
|
|
@@ -92384,30 +95856,39 @@ function compileSpec(args) {
|
|
|
92384
95856
|
const { workspace, lowerer, funcDecl, argTypes, nargout } = args;
|
|
92385
95857
|
workspace.finalize();
|
|
92386
95858
|
const widenedArgTypes = argTypes.map(withoutExact);
|
|
92387
|
-
const
|
|
92388
|
-
|
|
92389
|
-
|
|
92390
|
-
|
|
92391
|
-
|
|
92392
|
-
|
|
92393
|
-
|
|
92394
|
-
|
|
92395
|
-
|
|
92396
|
-
|
|
92397
|
-
|
|
92398
|
-
|
|
92399
|
-
|
|
92400
|
-
|
|
92401
|
-
|
|
92402
|
-
|
|
92403
|
-
|
|
92404
|
-
|
|
92405
|
-
|
|
92406
|
-
|
|
92407
|
-
|
|
92408
|
-
|
|
92409
|
-
|
|
92410
|
-
|
|
95859
|
+
const before = new Set(lowerer.specializations.keys());
|
|
95860
|
+
try {
|
|
95861
|
+
const spec = specializeUserFunction.call(
|
|
95862
|
+
lowerer,
|
|
95863
|
+
funcDecl,
|
|
95864
|
+
widenedArgTypes,
|
|
95865
|
+
void 0,
|
|
95866
|
+
void 0,
|
|
95867
|
+
void 0,
|
|
95868
|
+
nargout,
|
|
95869
|
+
void 0
|
|
95870
|
+
);
|
|
95871
|
+
assertNoNonVoidBareExprStmts(spec);
|
|
95872
|
+
const prog = {
|
|
95873
|
+
topLevelStmts: [],
|
|
95874
|
+
functions: new Map(lowerer.specializations)
|
|
95875
|
+
};
|
|
95876
|
+
const { source, activatedSnippets } = emitJsProgram(prog, {
|
|
95877
|
+
workspace,
|
|
95878
|
+
exposeSpec: spec.cName
|
|
95879
|
+
});
|
|
95880
|
+
return {
|
|
95881
|
+
cName: spec.cName,
|
|
95882
|
+
source,
|
|
95883
|
+
activatedSnippets,
|
|
95884
|
+
outputTypes: spec.outputTypes
|
|
95885
|
+
};
|
|
95886
|
+
} catch (err) {
|
|
95887
|
+
for (const key of lowerer.specializations.keys()) {
|
|
95888
|
+
if (!before.has(key)) lowerer.specializations.delete(key);
|
|
95889
|
+
}
|
|
95890
|
+
throw err;
|
|
95891
|
+
}
|
|
92411
95892
|
}
|
|
92412
95893
|
function assertNoNonVoidBareExprStmts(spec) {
|
|
92413
95894
|
const walk2 = (stmts) => {
|
|
@@ -94057,7 +97538,7 @@ function emitNdScalarOffset(state, indices, baseCName, grow = false) {
|
|
|
94057
97538
|
}
|
|
94058
97539
|
return terms.join(" + ");
|
|
94059
97540
|
}
|
|
94060
|
-
function emitSliceSlotSetup(state, lines, indent, slotsTyped, baseCName, cleanups) {
|
|
97541
|
+
function emitSliceSlotSetup(state, lines, indent, slotsTyped, baseCName, cleanups, grow = false) {
|
|
94061
97542
|
const slotSrc = [];
|
|
94062
97543
|
for (let i = 0; i < slotsTyped.length; i++) {
|
|
94063
97544
|
const slot = slotsTyped[i];
|
|
@@ -94066,12 +97547,18 @@ function emitSliceSlotSetup(state, lines, indent, slotsTyped, baseCName, cleanup
|
|
|
94066
97547
|
lines.push(`${indent}long _mtoc2_n_${i} = ${baseCName}.dims[${i}];`);
|
|
94067
97548
|
slotSrc.push(kVar);
|
|
94068
97549
|
} else if (slot.kind === "Scalar") {
|
|
94069
|
-
|
|
97550
|
+
const axisFn = grow ? "mtoc2_idx_axis_grow" : "mtoc2_idx_axis";
|
|
97551
|
+
if (grow) {
|
|
97552
|
+
useRuntimeByName(state, "mtoc2_grow_bail");
|
|
97553
|
+
state.usedGrowBail = true;
|
|
97554
|
+
} else {
|
|
97555
|
+
useRuntimeByName(state, "mtoc2_oob_abort");
|
|
97556
|
+
}
|
|
94070
97557
|
const scalarStr = emitExpr2(slot.expr, state);
|
|
94071
97558
|
const loc = locStringOf(slot.span);
|
|
94072
97559
|
lines.push(`${indent}long _mtoc2_n_${i} = 1;`);
|
|
94073
97560
|
lines.push(
|
|
94074
|
-
`${indent}long _mtoc2_src_${i} =
|
|
97561
|
+
`${indent}long _mtoc2_src_${i} = ${axisFn}(&${baseCName}, ${i}, mtoc2_to_idx(${scalarStr}), ${loc});`
|
|
94075
97562
|
);
|
|
94076
97563
|
slotSrc.push(`_mtoc2_src_${i}`);
|
|
94077
97564
|
} else if (slot.kind === "IndexVec") {
|
|
@@ -94461,7 +97948,10 @@ function emitIndexSliceStore(s, indent, state) {
|
|
|
94461
97948
|
lines,
|
|
94462
97949
|
`${indent} `,
|
|
94463
97950
|
s.index,
|
|
94464
|
-
baseCName
|
|
97951
|
+
baseCName,
|
|
97952
|
+
void 0,
|
|
97953
|
+
/*grow=*/
|
|
97954
|
+
true
|
|
94465
97955
|
);
|
|
94466
97956
|
const totalParts = [];
|
|
94467
97957
|
for (let i = 0; i < ndim; i++) totalParts.push(`_mtoc2_n_${i}`);
|
|
@@ -95521,40 +99011,48 @@ function compileSpecC(args) {
|
|
|
95521
99011
|
const { workspace, lowerer, funcDecl, argTypes, nargout } = args;
|
|
95522
99012
|
workspace.finalize();
|
|
95523
99013
|
const widenedArgTypes = argTypes.map(withoutExact);
|
|
95524
|
-
const
|
|
95525
|
-
|
|
95526
|
-
|
|
95527
|
-
|
|
95528
|
-
|
|
95529
|
-
|
|
95530
|
-
|
|
95531
|
-
|
|
95532
|
-
|
|
95533
|
-
|
|
95534
|
-
|
|
95535
|
-
|
|
95536
|
-
|
|
95537
|
-
|
|
95538
|
-
|
|
95539
|
-
|
|
95540
|
-
|
|
95541
|
-
|
|
95542
|
-
|
|
95543
|
-
|
|
99014
|
+
const before = new Set(lowerer.specializations.keys());
|
|
99015
|
+
try {
|
|
99016
|
+
const spec = specializeUserFunction.call(
|
|
99017
|
+
lowerer,
|
|
99018
|
+
funcDecl,
|
|
99019
|
+
widenedArgTypes,
|
|
99020
|
+
void 0,
|
|
99021
|
+
void 0,
|
|
99022
|
+
void 0,
|
|
99023
|
+
nargout,
|
|
99024
|
+
void 0
|
|
99025
|
+
);
|
|
99026
|
+
assertNoNonVoidBareExprStmts2(spec);
|
|
99027
|
+
const prog = {
|
|
99028
|
+
topLevelStmts: [],
|
|
99029
|
+
functions: new Map(lowerer.specializations)
|
|
99030
|
+
};
|
|
99031
|
+
const checkEntryOutputs = args.entrySynthetic !== true;
|
|
99032
|
+
assertDefiniteAssignment(spec, { checkOutputs: checkEntryOutputs });
|
|
99033
|
+
for (const fn of prog.functions.values()) {
|
|
99034
|
+
if (fn.cName === spec.cName) continue;
|
|
99035
|
+
assertDefiniteAssignment(fn, { checkOutputs: true });
|
|
99036
|
+
}
|
|
99037
|
+
const source = emitProgram(prog, {
|
|
99038
|
+
workspace,
|
|
99039
|
+
exposeSpec: spec.cName
|
|
99040
|
+
});
|
|
99041
|
+
return {
|
|
99042
|
+
cName: spec.cName,
|
|
99043
|
+
source,
|
|
99044
|
+
// The C emit doesn't currently expose its activated-snippet set
|
|
99045
|
+
// through emitProgram's return; the .so build doesn't need it.
|
|
99046
|
+
// Diagnostic field kept for symmetry with `compileSpec` (JS).
|
|
99047
|
+
activatedSnippets: [],
|
|
99048
|
+
signature: buildSignature(spec)
|
|
99049
|
+
};
|
|
99050
|
+
} catch (err) {
|
|
99051
|
+
for (const key of lowerer.specializations.keys()) {
|
|
99052
|
+
if (!before.has(key)) lowerer.specializations.delete(key);
|
|
99053
|
+
}
|
|
99054
|
+
throw err;
|
|
95544
99055
|
}
|
|
95545
|
-
const source = emitProgram(prog, {
|
|
95546
|
-
workspace,
|
|
95547
|
-
exposeSpec: spec.cName
|
|
95548
|
-
});
|
|
95549
|
-
return {
|
|
95550
|
-
cName: spec.cName,
|
|
95551
|
-
source,
|
|
95552
|
-
// The C emit doesn't currently expose its activated-snippet set
|
|
95553
|
-
// through emitProgram's return; the .so build doesn't need it.
|
|
95554
|
-
// Diagnostic field kept for symmetry with `compileSpec` (JS).
|
|
95555
|
-
activatedSnippets: [],
|
|
95556
|
-
signature: buildSignature(spec)
|
|
95557
|
-
};
|
|
95558
99056
|
}
|
|
95559
99057
|
function buildSignature(spec) {
|
|
95560
99058
|
const params = spec.cParams.map((cName, i) => ({
|
|
@@ -96616,7 +100114,17 @@ function jitTypeToCompilerType(jt) {
|
|
|
96616
100114
|
case "char":
|
|
96617
100115
|
return { kind: "Char" };
|
|
96618
100116
|
// Kinds the JIT path doesn't accept yet — fall through to interp.
|
|
96619
|
-
case "struct":
|
|
100117
|
+
case "struct": {
|
|
100118
|
+
if (jt.fields === void 0) return null;
|
|
100119
|
+
const names = Object.keys(jt.fields).sort();
|
|
100120
|
+
const fields = [];
|
|
100121
|
+
for (const name of names) {
|
|
100122
|
+
const fty = jitTypeToCompilerType(jt.fields[name]);
|
|
100123
|
+
if (fty === null) return null;
|
|
100124
|
+
fields.push({ name, ty: fty });
|
|
100125
|
+
}
|
|
100126
|
+
return { kind: "Struct", fields };
|
|
100127
|
+
}
|
|
96620
100128
|
case "struct_array":
|
|
96621
100129
|
case "class_instance":
|
|
96622
100130
|
case "sparse_matrix":
|
|
@@ -96662,11 +100170,20 @@ function numblToJit(v, paramType) {
|
|
|
96662
100170
|
if (isRuntimeComplexNumber(v)) {
|
|
96663
100171
|
return { re: v.re, im: v.im };
|
|
96664
100172
|
}
|
|
100173
|
+
if (isRuntimeStruct(v)) {
|
|
100174
|
+
const sty = paramType?.kind === "Struct" ? paramType : void 0;
|
|
100175
|
+
const out = {};
|
|
100176
|
+
for (const [name, fv] of v.fields) {
|
|
100177
|
+
const fty = sty?.fields.find((f) => f.name === name)?.ty;
|
|
100178
|
+
out[name] = numblToJit(fv, fty);
|
|
100179
|
+
}
|
|
100180
|
+
return out;
|
|
100181
|
+
}
|
|
96665
100182
|
throw new Error(
|
|
96666
100183
|
`numblToJit: unsupported RuntimeValue (executor should have declined)`
|
|
96667
100184
|
);
|
|
96668
100185
|
}
|
|
96669
|
-
function jitToNumbl(v) {
|
|
100186
|
+
function jitToNumbl(v, retType) {
|
|
96670
100187
|
if (typeof v === "number") return v;
|
|
96671
100188
|
if (typeof v === "boolean") return v;
|
|
96672
100189
|
if (typeof v === "string") return v;
|
|
@@ -96689,6 +100206,14 @@ function jitToNumbl(v) {
|
|
|
96689
100206
|
if (typeof tagged.re === "number" && typeof tagged.im === "number") {
|
|
96690
100207
|
return new RuntimeComplexNumber(tagged.re, tagged.im);
|
|
96691
100208
|
}
|
|
100209
|
+
if (retType?.kind === "Struct") {
|
|
100210
|
+
const fields = /* @__PURE__ */ new Map();
|
|
100211
|
+
for (const f of retType.fields) {
|
|
100212
|
+
const fv = v[f.name];
|
|
100213
|
+
if (fv !== void 0) fields.set(f.name, jitToNumbl(fv, f.ty));
|
|
100214
|
+
}
|
|
100215
|
+
return new RuntimeStruct(fields);
|
|
100216
|
+
}
|
|
96692
100217
|
throw new Error(`jitToNumbl: unrecognized return shape`);
|
|
96693
100218
|
}
|
|
96694
100219
|
function isGrowBail(e) {
|
|
@@ -96762,7 +100287,8 @@ var jitCallExecutor = {
|
|
|
96762
100287
|
name: "jit-call",
|
|
96763
100288
|
propose(lowered, ctx) {
|
|
96764
100289
|
if (lowered.kind !== "call") return null;
|
|
96765
|
-
if (ctx.interp.loopDepth > 0
|
|
100290
|
+
if (ctx.interp.loopDepth > 0 && ctx.interp.jitDeclinedLoopDepth === 0)
|
|
100291
|
+
return null;
|
|
96766
100292
|
const classification = lowered.classification;
|
|
96767
100293
|
if (ctx.interp.optimization === "2" && classification.assertsCJit) {
|
|
96768
100294
|
return null;
|
|
@@ -96794,7 +100320,7 @@ var jitCallExecutor = {
|
|
|
96794
100320
|
compile(d, ctx) {
|
|
96795
100321
|
const { workspace, lowerer } = getOrCreateSession(ctx.interp);
|
|
96796
100322
|
try {
|
|
96797
|
-
const { source, cName } = compileSpec({
|
|
100323
|
+
const { source, cName, outputTypes } = compileSpec({
|
|
96798
100324
|
workspace,
|
|
96799
100325
|
lowerer,
|
|
96800
100326
|
funcDecl: synthesizeFuncStmt(d.fn),
|
|
@@ -96810,12 +100336,13 @@ var jitCallExecutor = {
|
|
|
96810
100336
|
);
|
|
96811
100337
|
const factory = new Function(source)();
|
|
96812
100338
|
const specFn = factory(buildHostHelpers(interp.rt));
|
|
96813
|
-
return { specFn };
|
|
100339
|
+
return { specFn, outputTypes };
|
|
96814
100340
|
} catch (e) {
|
|
96815
100341
|
if (e instanceof UnsupportedConstruct || e instanceof TypeError2) {
|
|
96816
100342
|
recordJitDecline({
|
|
96817
100343
|
message: e.message,
|
|
96818
100344
|
kind: e.constructor.name,
|
|
100345
|
+
at: e.span ? { file: e.span.file, start: e.span.start } : void 0,
|
|
96819
100346
|
where: "jit-call"
|
|
96820
100347
|
});
|
|
96821
100348
|
return null;
|
|
@@ -96838,9 +100365,11 @@ var jitCallExecutor = {
|
|
|
96838
100365
|
`jit-call: expected array for nargout=${d.nargout}, got ${typeof result}`
|
|
96839
100366
|
);
|
|
96840
100367
|
}
|
|
96841
|
-
return {
|
|
100368
|
+
return {
|
|
100369
|
+
result: result.map((v, i) => jitToNumbl(v, compiled.outputTypes[i]))
|
|
100370
|
+
};
|
|
96842
100371
|
}
|
|
96843
|
-
return { result: jitToNumbl(result) };
|
|
100372
|
+
return { result: jitToNumbl(result, compiled.outputTypes[0]) };
|
|
96844
100373
|
} catch (e) {
|
|
96845
100374
|
if (isGrowBail(e)) {
|
|
96846
100375
|
ctx.interp.onJitBail?.(
|
|
@@ -96884,7 +100413,8 @@ var jitLoopExecutor = {
|
|
|
96884
100413
|
name: "jit-loop",
|
|
96885
100414
|
propose(lowered, ctx) {
|
|
96886
100415
|
if (lowered.kind !== "loop") return null;
|
|
96887
|
-
if (ctx.interp.loopDepth > 0
|
|
100416
|
+
if (ctx.interp.loopDepth > 0 && ctx.interp.jitDeclinedLoopDepth === 0)
|
|
100417
|
+
return null;
|
|
96888
100418
|
const classification = lowered.classification;
|
|
96889
100419
|
if (ctx.interp.optimization === "2" && classification.assertsCJit) {
|
|
96890
100420
|
return null;
|
|
@@ -96926,7 +100456,7 @@ var jitLoopExecutor = {
|
|
|
96926
100456
|
);
|
|
96927
100457
|
const nargout = d.outputs.length;
|
|
96928
100458
|
try {
|
|
96929
|
-
const { source, cName } = compileSpec({
|
|
100459
|
+
const { source, cName, outputTypes } = compileSpec({
|
|
96930
100460
|
workspace,
|
|
96931
100461
|
lowerer,
|
|
96932
100462
|
funcDecl,
|
|
@@ -96941,12 +100471,13 @@ var jitLoopExecutor = {
|
|
|
96941
100471
|
);
|
|
96942
100472
|
const factory = new Function(source)();
|
|
96943
100473
|
const specFn = factory(buildHostHelpers(interp.rt));
|
|
96944
|
-
return { specFn };
|
|
100474
|
+
return { specFn, outputTypes };
|
|
96945
100475
|
} catch (e) {
|
|
96946
100476
|
if (e instanceof UnsupportedConstruct || e instanceof TypeError2) {
|
|
96947
100477
|
recordJitDecline({
|
|
96948
100478
|
message: e.message,
|
|
96949
100479
|
kind: e.constructor.name,
|
|
100480
|
+
at: e.span ? { file: e.span.file, start: e.span.start } : void 0,
|
|
96950
100481
|
where: "jit-loop"
|
|
96951
100482
|
});
|
|
96952
100483
|
return null;
|
|
@@ -96971,7 +100502,9 @@ var jitLoopExecutor = {
|
|
|
96971
100502
|
if (d.outputs.length === 0) {
|
|
96972
100503
|
} else if (d.outputs.length === 1) {
|
|
96973
100504
|
if (result !== void 0) {
|
|
96974
|
-
const rv = ensureRuntimeValue(
|
|
100505
|
+
const rv = ensureRuntimeValue(
|
|
100506
|
+
jitToNumbl(result, compiled.outputTypes[0])
|
|
100507
|
+
);
|
|
96975
100508
|
interp.env.set(d.outputs[0], rv);
|
|
96976
100509
|
}
|
|
96977
100510
|
} else {
|
|
@@ -96983,7 +100516,9 @@ var jitLoopExecutor = {
|
|
|
96983
100516
|
for (let i = 0; i < d.outputs.length; i++) {
|
|
96984
100517
|
const elt = result[i];
|
|
96985
100518
|
if (elt !== void 0) {
|
|
96986
|
-
const rv = ensureRuntimeValue(
|
|
100519
|
+
const rv = ensureRuntimeValue(
|
|
100520
|
+
jitToNumbl(elt, compiled.outputTypes[i])
|
|
100521
|
+
);
|
|
96987
100522
|
interp.env.set(d.outputs[i], rv);
|
|
96988
100523
|
}
|
|
96989
100524
|
}
|
|
@@ -97071,7 +100606,7 @@ var jitTopLevelExecutor = {
|
|
|
97071
100606
|
);
|
|
97072
100607
|
const nargout = d.outputs.length;
|
|
97073
100608
|
try {
|
|
97074
|
-
const { source, cName } = compileSpec({
|
|
100609
|
+
const { source, cName, outputTypes } = compileSpec({
|
|
97075
100610
|
workspace,
|
|
97076
100611
|
lowerer,
|
|
97077
100612
|
funcDecl,
|
|
@@ -97086,12 +100621,13 @@ var jitTopLevelExecutor = {
|
|
|
97086
100621
|
);
|
|
97087
100622
|
const factory = new Function(source)();
|
|
97088
100623
|
const specFn = factory(buildHostHelpers(interp.rt));
|
|
97089
|
-
return { specFn, nargout };
|
|
100624
|
+
return { specFn, nargout, outputTypes };
|
|
97090
100625
|
} catch (e) {
|
|
97091
100626
|
if (e instanceof UnsupportedConstruct || e instanceof TypeError2) {
|
|
97092
100627
|
recordJitDecline({
|
|
97093
100628
|
message: e.message,
|
|
97094
100629
|
kind: e.constructor.name,
|
|
100630
|
+
at: e.span ? { file: e.span.file, start: e.span.start } : void 0,
|
|
97095
100631
|
where: "jit-top-level"
|
|
97096
100632
|
});
|
|
97097
100633
|
return null;
|
|
@@ -97116,7 +100652,9 @@ var jitTopLevelExecutor = {
|
|
|
97116
100652
|
if (d.outputs.length === 0) {
|
|
97117
100653
|
} else if (d.outputs.length === 1) {
|
|
97118
100654
|
if (result !== void 0) {
|
|
97119
|
-
const rv = ensureRuntimeValue(
|
|
100655
|
+
const rv = ensureRuntimeValue(
|
|
100656
|
+
jitToNumbl(result, compiled.outputTypes[0])
|
|
100657
|
+
);
|
|
97120
100658
|
interp.env.set(d.outputs[0], rv);
|
|
97121
100659
|
}
|
|
97122
100660
|
} else {
|
|
@@ -97128,7 +100666,9 @@ var jitTopLevelExecutor = {
|
|
|
97128
100666
|
for (let i = 0; i < d.outputs.length; i++) {
|
|
97129
100667
|
const elt = result[i];
|
|
97130
100668
|
if (elt !== void 0) {
|
|
97131
|
-
const rv = ensureRuntimeValue(
|
|
100669
|
+
const rv = ensureRuntimeValue(
|
|
100670
|
+
jitToNumbl(elt, compiled.outputTypes[i])
|
|
100671
|
+
);
|
|
97132
100672
|
interp.env.set(d.outputs[i], rv);
|
|
97133
100673
|
}
|
|
97134
100674
|
}
|
|
@@ -99950,7 +103490,7 @@ static void mtoc2__format_walk(mtoc2__writer_fn writer, void *ctx,
|
|
|
99950
103490
|
"warning_fmt.h": '/* mtoc2 runtime helper: warning \u2014 write a `Warning: <formatted text>\\n`\n * line to stdout. Matches numbl\'s `warning(...)` shape\n * (numbl/src/numbl-core/runtime/specialBuiltins.ts:190 \u2014 `rt.output("Warning: " + ... + "\\n")`).\n *\n * Two forms:\n * - `mtoc2_warning_fmt(fmt, nargs, args)` \u2014 bare `warning(fmt, ...)`.\n * - `mtoc2_warning_fmt_id(id, fmt, nargs, args)` \u2014 id-bearing\n * `warning(\'id:topic\', fmt, ...)`. The c-aot path ignores the id\n * (it has no `lastwarn`-style state to update); the JS sibling\n * matches numbl by including the id only in side-channel state if\n * we ever add it. For now both forms produce the same prefix.\n *\n * Format engine is shared with sprintf / fprintf \u2014 see format_engine.h.\n */\n\n#include <stdio.h>\n\nstatic void mtoc2__warning_writer(void *ctx, const char *bytes, long len) {\n (void)ctx;\n if (len > 0) fwrite(bytes, 1, (size_t)len, stdout);\n}\n\nstatic void mtoc2_warning_fmt(mtoc2_text_view_t fmt, int nargs,\n const mtoc2_fprintf_arg_t *args) {\n fputs("Warning: ", stdout);\n mtoc2__format_walk(mtoc2__warning_writer, NULL, fmt, nargs, args);\n fputc(\'\\n\', stdout);\n}\n\nstatic void mtoc2_warning_fmt_id(mtoc2_text_view_t id, mtoc2_text_view_t fmt,\n int nargs, const mtoc2_fprintf_arg_t *args) {\n (void)id; /* c-aot has no lastwarn state to set */\n mtoc2_warning_fmt(fmt, nargs, args);\n}\n',
|
|
99951
103491
|
"plot_dispatch.h": '/* mtoc2 runtime: plot dispatch \u2014 single helper for every plotting\n * builtin (`plot`, `surf`, `imagesc`, `bar`, `figure`, `hold`, \u2026).\n *\n * Numbl handles plotting by accumulating an in-memory "instruction\n * stream" that a separate viewer renders; the CLI never writes plot\n * output to stdout. mtoc2 mirrors that data-shape on the wire: each\n * plotting call emits one line of JSON on stdout, prefixed by the\n * ASCII RS (`\\x1e`) sentinel plus the literal tag `mtoc2:plot\\t`.\n * A launcher / viewer process tees stdout, splits on the prefix,\n * and feeds the records into numbl\'s own plot module \u2014 no C\n * plotting code needed.\n *\n * Why RS as the sentinel: RS (0x1E, "record separator") is a C0\n * control character that practical numeric / text output never\n * contains, so the splitter can identify plot lines purely by\n * prefix without escaping user output. The cross-runner drops\n * these lines globally before the byte-for-byte stdout compare\n * (numbl produces no such lines, so the drop is a no-op there).\n *\n * The wire shape per call is:\n *\n * \\x1e mtoc2:plot \\t {"call":"<name>","args":[<arg>, ...]} \\n\n *\n * Argument encoding (one element per source-level arg):\n * double -> bare numeric (NaN / \xB1Infinity rendered as `null`,\n * matching JS `JSON.stringify` behavior so the\n * viewer round-trips through `JSON.parse`)\n * text -> {"kind":"text","data":"<utf-8 with JSON escapes>"}\n * (char and string sources both flatten to this \u2014\n * MATLAB plot semantics don\'t distinguish them)\n * tensor -> {"kind":"tensor","dims":[d1,...,dN],\n * "data":[v1, ...]} (column-major flatten;\n * non-finite elements as `null`)\n *\n * Argument transport reuses `mtoc2_fprintf_arg_t` from\n * `format_engine.h` (slot kinds DOUBLE / TEXT / TENSOR). Type-level\n * rejection of unsupported arg kinds (complex / struct / class /\n * handle / Void / Unknown) happens at lowering \u2014 the dispatcher\n * itself never receives them.\n *\n * `fflush(stdout)` after every record makes plots stream live when\n * stdout is piped to a viewer; cost is one syscall per call and\n * negligible compared to user-level disp output.\n */\n\nstatic void mtoc2__plot_emit(const char *s, long n) {\n if (n > 0) fwrite(s, 1, (size_t)n, stdout);\n}\n\nstatic void mtoc2__plot_emit_cstr(const char *s) {\n mtoc2__plot_emit(s, (long)strlen(s));\n}\n\nstatic void mtoc2__plot_emit_double(double x) {\n if (!isfinite(x)) {\n mtoc2__plot_emit_cstr("null");\n return;\n }\n char buf[32];\n long n;\n if (fabs(x) < 1e16 && x == (double)(long long)x) {\n n = (long)snprintf(buf, sizeof(buf), "%lld", (long long)x);\n } else {\n n = (long)snprintf(buf, sizeof(buf), "%.17g", x);\n }\n mtoc2__plot_emit(buf, n);\n}\n\nstatic void mtoc2__plot_emit_json_string(const char *data, long len) {\n fputc(\'"\', stdout);\n for (long i = 0; i < len; i++) {\n unsigned char c = (unsigned char)data[i];\n if (c == \'"\' || c == \'\\\\\') {\n char esc[2] = { \'\\\\\', (char)c };\n mtoc2__plot_emit(esc, 2);\n } else if (c == \'\\n\') {\n mtoc2__plot_emit("\\\\n", 2);\n } else if (c == \'\\r\') {\n mtoc2__plot_emit("\\\\r", 2);\n } else if (c == \'\\t\') {\n mtoc2__plot_emit("\\\\t", 2);\n } else if (c == \'\\b\') {\n mtoc2__plot_emit("\\\\b", 2);\n } else if (c == \'\\f\') {\n mtoc2__plot_emit("\\\\f", 2);\n } else if (c < 0x20) {\n char esc[8];\n long n = (long)snprintf(esc, sizeof(esc), "\\\\u%04x", c);\n mtoc2__plot_emit(esc, n);\n } else {\n /* Bytes \u2265 0x20 (including high-bit UTF-8 continuation) pass\n * through verbatim; JSON allows raw UTF-8 in string content. */\n fputc((int)c, stdout);\n }\n }\n fputc(\'"\', stdout);\n}\n\nstatic void mtoc2__plot_emit_arg(const mtoc2_fprintf_arg_t *a) {\n switch (a->kind) {\n case MTOC2_FA_DOUBLE:\n mtoc2__plot_emit_double(a->u.d);\n return;\n case MTOC2_FA_TEXT: {\n mtoc2_text_view_t tv = a->u.t;\n long n = tv.len > 0 ? tv.len : 0;\n const char *data = tv.data ? tv.data : "";\n mtoc2__plot_emit_cstr("{\\"kind\\":\\"text\\",\\"data\\":");\n mtoc2__plot_emit_json_string(data, n);\n fputc(\'}\', stdout);\n return;\n }\n case MTOC2_FA_TENSOR: {\n const mtoc2_tensor_t *t = a->u.tensor;\n mtoc2__plot_emit_cstr("{\\"kind\\":\\"tensor\\",\\"dims\\":[");\n long total = 1;\n for (int k = 0; k < t->ndim; k++) {\n if (k > 0) fputc(\',\', stdout);\n char buf[24];\n long n = (long)snprintf(buf, sizeof(buf), "%ld", (long)t->dims[k]);\n mtoc2__plot_emit(buf, n);\n total *= t->dims[k];\n }\n mtoc2__plot_emit_cstr("],\\"data\\":[");\n for (long i = 0; i < total; i++) {\n if (i > 0) fputc(\',\', stdout);\n mtoc2__plot_emit_double(t->real[i]);\n }\n mtoc2__plot_emit_cstr("]}");\n return;\n }\n default:\n mtoc2__plot_emit_cstr("null");\n return;\n }\n}\n\nstatic void mtoc2_plot_dispatch(const char *name, int nargs,\n const mtoc2_fprintf_arg_t *args) {\n mtoc2__plot_emit_cstr("\\x1emtoc2:plot\\t{\\"call\\":");\n mtoc2__plot_emit_json_string(name, (long)strlen(name));\n mtoc2__plot_emit_cstr(",\\"args\\":[");\n for (int i = 0; i < nargs; i++) {\n if (i > 0) fputc(\',\', stdout);\n mtoc2__plot_emit_arg(&args[i]);\n }\n mtoc2__plot_emit_cstr("]}\\n");\n fflush(stdout);\n}\n',
|
|
99952
103492
|
"cdiv.h": "/* mtoc2 runtime helper: scalar complex division `a / b` matching\n * numbl's signed-Inf-on-zero-divisor behavior.\n *\n * C99's `_Complex` division is unspecified at the signs of NaN /\n * Inf results when the divisor is zero, so divisions like\n * `(1 + 2i) / 0` can disagree between compilers. Numbl uses Smith's\n * algorithm (which factors out the larger-magnitude divisor\n * component) and explicit \xB10 detection to land on the same byte\n * stream regardless of the underlying libc. This helper mirrors\n * that path so cross-runner output stays aligned.\n */\n\n#include <complex.h>\n#include <math.h>\n\nstatic double mtoc2_signed_inf(double x) {\n return x > 0 ? INFINITY : (x < 0 ? -INFINITY : 0.0);\n}\n\n/* Pack re/im into a complex without the `im * I` trap: `INFINITY * I`\n * is `NaN + INFINITY*i` (0*Inf in the real lane), which would corrupt a\n * signed-Inf result. __builtin_complex (gcc/clang) sets the components\n * directly; CMPLX is the C11 fallback. */\nstatic double _Complex mtoc2_cpack(double re, double im) {\n#if defined(__clang__) || defined(__GNUC__)\n return __builtin_complex(re, im);\n#else\n return CMPLX(re, im);\n#endif\n}\n\nstatic double _Complex mtoc2_cdiv(double _Complex a, double _Complex b) {\n double ar = creal(a), ai = cimag(a);\n double br = creal(b), bi = cimag(b);\n /* Zero divisor: match the interpreter (helpers/arithmetic.ts) \u2014 0/0 is\n * NaN, a nonzero numerator yields a signed Inf per component. Smith's\n * algorithm below would otherwise produce NaN+NaNi here. */\n if (br == 0.0 && bi == 0.0) {\n if (ar == 0.0 && ai == 0.0) return mtoc2_cpack(NAN, 0.0);\n return mtoc2_cpack(mtoc2_signed_inf(ar), mtoc2_signed_inf(ai));\n }\n /* Standard Smith's: pick the scaling that puts the larger-magnitude\n * divisor component in the denominator. */\n if (fabs(br) >= fabs(bi)) {\n double r = bi / br;\n double den = br + r * bi;\n return (ar + ai * r) / den + ((ai - ar * r) / den) * I;\n }\n double r = br / bi;\n double den = bi + r * br;\n return (ar * r + ai) / den + ((ai * r - ar) / den) * I;\n}\n",
|
|
99953
|
-
"cscalar.h": "/* mtoc2 runtime helpers: scalar complex operations as explicit\n * function calls.\n *\n * Every `double _Complex` operation mtoc2 emits into user code routes\n * through one of these helpers instead of relying on C99's operator\n * overloading or the `I` macro. On the C path each is `static inline`\n * and the compiler folds back to the same instructions C99 would have\n * generated. The win is parallelism with the js-aot path: the JS\n * sibling (`cscalar.js`) ships a matching set of helpers that operate\n * on a `{re, im}` JS representation, so user code emitted by `emitJs`\n * uses the same call shape the C emitter would have produced.\n *\n * Division and pow are NOT defined here:\n * - `mtoc2_cdiv` lives in `cdiv.h` because it needs Smith's\n * algorithm + signed-zero detection to match numbl byte-for-byte.\n * - `cpow` is emitted directly today (still a libm call, not an\n * operator); a `mtoc2_cpow` wrapper lands when the JS side grows\n * a power helper.\n */\n\n#include <complex.h>\n#include <math.h>\n\nstatic inline double _Complex mtoc2_cmake(double re, double im) {\n return re + im * I;\n}\nstatic inline double mtoc2_creal(double _Complex z) { return creal(z); }\nstatic inline double mtoc2_cimag(double _Complex z) { return cimag(z); }\nstatic inline double _Complex mtoc2_cadd(double _Complex a, double _Complex b) { return a + b; }\nstatic inline double _Complex mtoc2_csub(double _Complex a, double _Complex b) { return a - b; }\nstatic inline double _Complex mtoc2_cmul(double _Complex a, double _Complex b) { return a * b; }\nstatic inline double _Complex mtoc2_cneg(double _Complex z) { return -z; }\nstatic inline double _Complex mtoc2_cconj(double _Complex z) { return conj(z); }\nstatic inline double mtoc2_cabs(double _Complex z) {\n return hypot(creal(z), cimag(z));\n}\nstatic inline double mtoc2_cangle(double _Complex z) {\n return atan2(cimag(z), creal(z));\n}\nstatic inline int mtoc2_cnonzero(double _Complex z) {\n return creal(z) != 0.0 || cimag(z) != 0.0;\n}\nstatic inline int mtoc2_ceq(double _Complex a, double _Complex b) {\n return creal(a) == creal(b) && cimag(a) == cimag(b);\n}\nstatic inline int mtoc2_cne(double _Complex a, double _Complex b) {\n return creal(a) != creal(b) || cimag(a) != cimag(b);\n}\nstatic inline double _Complex mtoc2_cpow(double _Complex a, double _Complex b) {\n return cpow(a, b);\n}\n\n/* Unary complex math \u2014 `<complex.h>` wrappers + a handful of\n * derived helpers C99 doesn't ship (log2/log10, MATLAB-style\n * componentwise rounding, signum). Same `mtoc2_c*` shape as the\n * core scalar helpers above so the c2js backend can substitute\n * its own `{re, im}` JS implementations.\n *\n * The rounding helpers (floor/ceil/round/fix) match MATLAB by\n * applying the rounding mode to each component independently and\n * returning a complex result; the magnitude is NOT preserved\n * (MATLAB's `floor([1.5 + 1.5i])` returns `1 + 1i`, not the\n * floor of the magnitude).\n *\n * `mtoc2_csign(z)` matches MATLAB: `z/|z|` for nonzero, exactly\n * `0 + 0i` for the zero scalar. */\nstatic inline double _Complex mtoc2_csqrt(double _Complex z) { return csqrt(z)
|
|
103493
|
+
"cscalar.h": "/* mtoc2 runtime helpers: scalar complex operations as explicit\n * function calls.\n *\n * Every `double _Complex` operation mtoc2 emits into user code routes\n * through one of these helpers instead of relying on C99's operator\n * overloading or the `I` macro. On the C path each is `static inline`\n * and the compiler folds back to the same instructions C99 would have\n * generated. The win is parallelism with the js-aot path: the JS\n * sibling (`cscalar.js`) ships a matching set of helpers that operate\n * on a `{re, im}` JS representation, so user code emitted by `emitJs`\n * uses the same call shape the C emitter would have produced.\n *\n * Division and pow are NOT defined here:\n * - `mtoc2_cdiv` lives in `cdiv.h` because it needs Smith's\n * algorithm + signed-zero detection to match numbl byte-for-byte.\n * - `cpow` is emitted directly today (still a libm call, not an\n * operator); a `mtoc2_cpow` wrapper lands when the JS side grows\n * a power helper.\n */\n\n#include <complex.h>\n#include <math.h>\n\nstatic inline double _Complex mtoc2_cmake(double re, double im) {\n return re + im * I;\n}\nstatic inline double mtoc2_creal(double _Complex z) { return creal(z); }\nstatic inline double mtoc2_cimag(double _Complex z) { return cimag(z); }\nstatic inline double _Complex mtoc2_cadd(double _Complex a, double _Complex b) { return a + b; }\nstatic inline double _Complex mtoc2_csub(double _Complex a, double _Complex b) { return a - b; }\nstatic inline double _Complex mtoc2_cmul(double _Complex a, double _Complex b) { return a * b; }\nstatic inline double _Complex mtoc2_cneg(double _Complex z) { return -z; }\nstatic inline double _Complex mtoc2_cconj(double _Complex z) { return conj(z); }\nstatic inline double mtoc2_cabs(double _Complex z) {\n return hypot(creal(z), cimag(z));\n}\nstatic inline double mtoc2_cangle(double _Complex z) {\n return atan2(cimag(z), creal(z));\n}\nstatic inline int mtoc2_cnonzero(double _Complex z) {\n return creal(z) != 0.0 || cimag(z) != 0.0;\n}\nstatic inline int mtoc2_ceq(double _Complex a, double _Complex b) {\n return creal(a) == creal(b) && cimag(a) == cimag(b);\n}\nstatic inline int mtoc2_cne(double _Complex a, double _Complex b) {\n return creal(a) != creal(b) || cimag(a) != cimag(b);\n}\nstatic inline double _Complex mtoc2_cpow(double _Complex a, double _Complex b) {\n return cpow(a, b);\n}\n\n/* Unary complex math \u2014 `<complex.h>` wrappers + a handful of\n * derived helpers C99 doesn't ship (log2/log10, MATLAB-style\n * componentwise rounding, signum). Same `mtoc2_c*` shape as the\n * core scalar helpers above so the c2js backend can substitute\n * its own `{re, im}` JS implementations.\n *\n * The rounding helpers (floor/ceil/round/fix) match MATLAB by\n * applying the rounding mode to each component independently and\n * returning a complex result; the magnitude is NOT preserved\n * (MATLAB's `floor([1.5 + 1.5i])` returns `1 + 1i`, not the\n * floor of the magnitude).\n *\n * `mtoc2_csign(z)` matches MATLAB: `z/|z|` for nonzero, exactly\n * `0 + 0i` for the zero scalar. */\n/* True when z is a NaN on the real axis. The JIT lifts a real argument whose\n * sign it cannot prove onto these complex helpers, and MATLAB's sqrt(NaN) /\n * log(NaN) are a real NaN \u2014 so a lifted NaN must come back as NaN + 0i, not\n * 0 + NaN i. The lift is a compilation detail and must not be observable. */\nstatic inline int mtoc2_nan_on_real_axis(double _Complex z) {\n return cimag(z) == 0.0 && isnan(creal(z));\n}\nstatic inline double _Complex mtoc2_csqrt(double _Complex z) {\n if (mtoc2_nan_on_real_axis(z)) return mtoc2_cmake(creal(z), 0.0);\n return csqrt(z);\n}\nstatic inline double _Complex mtoc2_cexp(double _Complex z) { return cexp(z); }\nstatic inline double _Complex mtoc2_clog(double _Complex z) {\n if (mtoc2_nan_on_real_axis(z)) return mtoc2_cmake(creal(z), 0.0);\n return clog(z);\n}\nstatic inline double _Complex mtoc2_clog2(double _Complex z) {\n if (mtoc2_nan_on_real_axis(z)) return mtoc2_cmake(creal(z), 0.0);\n return clog(z) / log(2.0);\n}\nstatic inline double _Complex mtoc2_clog10(double _Complex z) {\n if (mtoc2_nan_on_real_axis(z)) return mtoc2_cmake(creal(z), 0.0);\n return clog(z) / log(10.0);\n}\nstatic inline double _Complex mtoc2_csin(double _Complex z) { return csin(z); }\nstatic inline double _Complex mtoc2_ccos(double _Complex z) { return ccos(z); }\nstatic inline double _Complex mtoc2_ctan(double _Complex z) { return ctan(z); }\nstatic inline double _Complex mtoc2_catan(double _Complex z) {\n /* Real-valued input: clean real atan (no spurious imaginary residue,\n no Inf/Inf NaN at large |re|). */\n if (cimag(z) == 0.0) return mtoc2_cmake(atan(creal(z)), 0.0);\n /* atan(z) = (i/2)*log((1 - iz)/(1 + iz)). MATLAB's branch for a\n pure-imaginary z with |z| > 1 is -pi/2 + ... (atan(2i) = -1.5708 +\n 0.5493i); libc catan uses the opposite +pi/2 Annex-G branch. Compute\n the formula here so the C path matches MATLAB and the JS runtime.\n Normalize a -0 imaginary part of the quotient to +0 (via +0.0) so\n clog picks the +pi branch \u2014 a -0 would flip it to -pi -> +pi/2. */\n double _Complex iz = mtoc2_cmake(-cimag(z), creal(z));\n double _Complex num = mtoc2_cmake(1.0 - creal(iz), -cimag(iz));\n double _Complex den = mtoc2_cmake(1.0 + creal(iz), cimag(iz));\n double _Complex q = num / den;\n double _Complex l = clog(mtoc2_cmake(creal(q), cimag(q) + 0.0));\n return mtoc2_cmake(-cimag(l) / 2.0, creal(l) / 2.0);\n}\n/* Hyperbolic sinh/cosh/tanh are entire functions (no branch cuts), so\n * C99's csinh/ccosh/ctanh agree with the JS componentwise formulas in\n * `cscalar.js` to within floating-point ULPs everywhere. */\nstatic inline double _Complex mtoc2_csinh(double _Complex z) { return csinh(z); }\nstatic inline double _Complex mtoc2_ccosh(double _Complex z) { return ccosh(z); }\nstatic inline double _Complex mtoc2_ctanh(double _Complex z) { return ctanh(z); }\nstatic inline double _Complex mtoc2_cfloor(double _Complex z) {\n return floor(creal(z)) + floor(cimag(z)) * I;\n}\nstatic inline double _Complex mtoc2_cceil(double _Complex z) {\n return ceil(creal(z)) + ceil(cimag(z)) * I;\n}\nstatic inline double _Complex mtoc2_cround(double _Complex z) {\n return round(creal(z)) + round(cimag(z)) * I;\n}\nstatic inline double _Complex mtoc2_cfix(double _Complex z) {\n return trunc(creal(z)) + trunc(cimag(z)) * I;\n}\nstatic inline double _Complex mtoc2_csign(double _Complex z) {\n double re = creal(z), im = cimag(z);\n if (re == 0.0 && im == 0.0) return 0.0;\n double m = hypot(re, im);\n return (re / m) + (im / m) * I;\n}\n",
|
|
99954
103494
|
"deep_clone.h": "/* JS-only snippet (paired with `deep_clone.js`).\n *\n * The C path's owned-value protocol (per-typedef `_copy` helpers\n * generated by `emitNamedTypedef`) provides the equivalent\n * always-copy semantics. This snippet exists only to give the\n * activation system a `.h` sibling for the JS-side\n * `mtoc2_deep_clone` helper; the C body is intentionally empty.\n */\n",
|
|
99955
103495
|
"isequal.h": "/* mtoc2 runtime helpers for `isequal` over real numeric values.\n *\n * Complex tensors, char / string, struct and cell comparison are\n * handled by the interpreter's `call` hook; the AOT `emitC` rejects\n * those argument combinations with `UnsupportedConstruct`. These two\n * helpers cover the dominant cases: tensor-vs-tensor and\n * scalar-vs-tensor over real data.\n *\n * Equality follows numbl's `valuesEqualSimple` / `tensorsEqual`:\n * same rank, same per-axis extent, element-for-element `==`\n * (so `NaN != NaN`, matching MATLAB / numbl).\n */\n\n/* Two real tensors: equal iff identical shape and data. */\nstatic double mtoc2_isequal_tt(mtoc2_tensor_t a, mtoc2_tensor_t b) {\n if (a.ndim != b.ndim) return 0.0;\n long n = 1;\n for (int i = 0; i < a.ndim; i++) {\n if (a.dims[i] != b.dims[i]) return 0.0;\n n *= a.dims[i];\n }\n for (long i = 0; i < n; i++) {\n if (a.real[i] != b.real[i]) return 0.0;\n }\n return 1.0;\n}\n\n/* Real scalar vs real tensor: equal iff the tensor holds exactly one\n * element equal to `s` (numbl treats a scalar as a 1\xD71 tensor). */\nstatic double mtoc2_isequal_st(double s, mtoc2_tensor_t t) {\n long n = 1;\n for (int i = 0; i < t.ndim; i++) n *= t.dims[i];\n if (n != 1) return 0.0;\n return t.real[0] == s ? 1.0 : 0.0;\n}\n",
|
|
99956
103496
|
"length.h": "/* mtoc runtime helper: MATLAB's `length(t)` on a multi-element tensor.\n *\n * Returns the size of the largest axis as a double, or 0.0 if any axis\n * has length 0. Mirrors MATLAB/numbl semantics. Scalar args don't reach\n * this helper \u2014 codegen emits the literal `1.0` directly because the C\n * arg is a bare `double`, not an `mtoc2_tensor_t`.\n */\n\nstatic double mtoc2_length(mtoc2_tensor_t t) {\n long max = 0;\n for (int i = 0; i < t.ndim; i++) {\n if (t.dims[i] == 0) return 0.0;\n if (t.dims[i] > max) max = t.dims[i];\n }\n return (double)max;\n}\n",
|
|
@@ -100487,7 +104027,8 @@ var cJitLoopExecutor = {
|
|
|
100487
104027
|
if (lowered.kind !== "loop") return null;
|
|
100488
104028
|
const bridge = ctx.interp.nativeBridge;
|
|
100489
104029
|
if (!bridge || !bridge.koffi) return null;
|
|
100490
|
-
if (ctx.interp.loopDepth > 0
|
|
104030
|
+
if (ctx.interp.loopDepth > 0 && ctx.interp.jitDeclinedLoopDepth === 0)
|
|
104031
|
+
return null;
|
|
100491
104032
|
const classification = lowered.classification;
|
|
100492
104033
|
if (classification.hasReturn) return null;
|
|
100493
104034
|
const compilerInputTypes = [];
|
|
@@ -100699,7 +104240,8 @@ var cJitCallExecutor = {
|
|
|
100699
104240
|
if (lowered.kind !== "call") return null;
|
|
100700
104241
|
const bridge = ctx.interp.nativeBridge;
|
|
100701
104242
|
if (!bridge || !bridge.koffi) return null;
|
|
100702
|
-
if (ctx.interp.loopDepth > 0
|
|
104243
|
+
if (ctx.interp.loopDepth > 0 && ctx.interp.jitDeclinedLoopDepth === 0)
|
|
104244
|
+
return null;
|
|
100703
104245
|
const classification = lowered.classification;
|
|
100704
104246
|
if (classification.nargout === 0) return null;
|
|
100705
104247
|
const compilerArgTypes = [];
|
|
@@ -101230,7 +104772,9 @@ Options (for run and eval):
|
|
|
101230
104772
|
|
|
101231
104773
|
Environment variables:
|
|
101232
104774
|
NUMBL_PATH Extra workspace directories (separated by ${delimiter})
|
|
101233
|
-
NUMBL_NO_NATIVE If set, do not load the native LAPACK addon
|
|
104775
|
+
NUMBL_NO_NATIVE If set, do not load the native LAPACK addon
|
|
104776
|
+
NUMBL_JIT_LOG If set, print every JIT decline (executor, source
|
|
104777
|
+
position, reason) to stderr`);
|
|
101234
104778
|
}
|
|
101235
104779
|
function parseOptions(args) {
|
|
101236
104780
|
const opts = {
|