UNPKG

robust-determinant

Version:
103 lines (92 loc) 2.58 kB
"use strict" var twoProduct = require("two-product") var robustSum = require("robust-sum") var robustScale = require("robust-scale") var compress = require("robust-compress") var NUM_EXPANDED = 6 function cofactor(m, c) { var result = new Array(m.length-1) for(var i=1; i<m.length; ++i) { var r = result[i-1] = new Array(m.length-1) for(var j=0,k=0; j<m.length; ++j) { if(j === c) { continue } r[k++] = m[i][j] } } return result } function matrix(n) { var result = new Array(n) for(var i=0; i<n; ++i) { result[i] = new Array(n) for(var j=0; j<n; ++j) { result[i][j] = ["m[", i, "][", j, "]"].join("") } } return result } function sign(n) { if(n & 1) { return "-" } return "" } function generateSum(expr) { if(expr.length === 1) { return expr[0] } else if(expr.length === 2) { return ["sum(", expr[0], ",", expr[1], ")"].join("") } else { var m = expr.length>>1 return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") } } function determinant(m) { if(m.length === 2) { return ["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("") } else { var expr = [] for(var i=0; i<m.length; ++i) { expr.push(["scale(", determinant(cofactor(m, i)), ",", sign(i), m[0][i], ")"].join("")) } return generateSum(expr) } } function compileDeterminant(n) { var proc = new Function("sum", "scale", "prod", "compress", [ "function robustDeterminant",n, "(m){return compress(", determinant(matrix(n)), ")};return robustDeterminant", n].join("")) return proc(robustSum, robustScale, twoProduct, compress) } var CACHE = [ function robustDeterminant0() { return [0] }, function robustDeterminant1(m) { return [m[0][0]] } ] function generateDispatch() { while(CACHE.length < NUM_EXPANDED) { CACHE.push(compileDeterminant(CACHE.length)) } var procArgs = [] var code = ["function robustDeterminant(m){switch(m.length){"] for(var i=0; i<NUM_EXPANDED; ++i) { procArgs.push("det" + i) code.push("case ", i, ":return det", i, "(m);") } code.push("}\ var det=CACHE[m.length];\ if(!det)\ det=CACHE[m.length]=gen(m.length);\ return det(m);\ }\ return robustDeterminant") procArgs.push("CACHE", "gen", code.join("")) var proc = Function.apply(undefined, procArgs) module.exports = proc.apply(undefined, CACHE.concat([CACHE, compileDeterminant])) for(var i=0; i<CACHE.length; ++i) { module.exports[i] = CACHE[i] } } generateDispatch()