function svd(matrix, tol = 1e-10) {
const A = matrix;
const size = math.size(A);
const m = size._data[0];
const n = size._data[1];
const U = math.zeros(m, m);
const S = math.zeros(m, n);
const V = math.zeros(n, n);
const ATA = math.multiply(math.transpose(A), A);
const AAT = math.multiply(A, math.transpose(A));
const eigen = math.eigs(ATA);
const sorted_indices = [...new Set(argSort(eigen.values.toArray()).reverse())];
const eigenvalues = eigen.values.subset(math.index(sorted_indices));
const eigenvectors = sorted_indices.map(i => eigen.eigenvectors[i].value);
const singular_values = math.map(eigenvalues, math.sqrt);
const non_zero_singular_values = math.map(singular_values, x => math.larger(x, tol));
const r = math.sum(non_zero_singular_values.map(x => x !== 0 ? 1 : 0));
return math.range(1,r)
S.subset(
math.index(math.range(1, r), math.range(1, r)),
math.diag(singular_values.subset(math.index(non_zero_singular_values)))
);
return {eigenvalues, eigenvectors}
const S_pseudo_inverse = math.pinv(S);
U.subset(
[":", `:{r}`],
math.multiply(A, eigenvectors.subset([":", `:{r}`]))
);
V.subset([":", `:{r}`], eigenvectors.subset([":", `:{r}`]));
return { U, S, V };
}