// matrix and vector functions. // // function vector_add(a, b, result){ if(!result) result = []; if(!a) throw "first argument to vector_add missing"; if(!b) throw "second argument to vector_add missing"; if(a.length > b.lemgth){ var tmp = a; a = b; b = tmp; } for(var i = 0; i < a.length; ++i){ result[i] = a[i] + b[i]; } for(var i = a.length; i < b.length; ++i){ result[i] = b[i]; } return result; } function vector_cpy(result, a){ if(!a) throw "first argument to vector_cpy missing"; for(var i = 0; i < a.length; ++i){ result[i] = a[i]; } } function vector_minus(a, b, result){ if(!result) result = []; if(!a) throw "first argument to vector_minus missing"; if(!b) throw "second argument to vector_minus missing"; var lim = Math.max(a.length, b.length); for(var i = 0; i < lim; ++i){ var aValue, bValue; if(i < a.length) aValue = a[i]; else aValue = 0; if(i < b.length) bValue = b[i]; else bValue = 0; result[i] = aValue - bValue; } return result; } function vector_dot(a, b){ var lim = Math.min(a.length, b.length); if(!a) throw "first argument to vector_dot missing"; if(!b) throw "second argument to vector_dot missing"; var result = 0; for(var i = 0; i < lim; ++i){ result += a[i] * b[i]; } return result; } function vector_norm(a){ if(!a) throw "argument to vector_norm missing"; return Math.sqrt(vector_dot(a,a)); } function vector_scale(a, s, result){ if(!a) throw "first argument to vector_scale missing"; if(s === undefined || s === null) throw "scalar argument to vector_scale missing"; if(!result) result = []; for(var i = 0; i < a.length; ++i){ result[i] = s * a[i]; } return result; } // returns true iff the zero tail padded vectors match function vector_cmp(a, b){ if(!a) throw "first argument to vector_cmp missing"; if(!b) throw "second argument to vector_cmp missing"; if(a.length > b.length){ var tmp = a; a = b; b = tmp; } for(var i = 0; i < a.length; ++i){ if(a[i] != b[i]) return false; } for(var i = a.length; i < b.length; ++i){ if(b[i] != 0) return false; } return true; } function vector_midpoint(a, b, result){ if(!a) throw "first argument to vector_midpoint missing"; if(!b) throw "second argument to vector_midpoint missing"; if(b.length > a.length){ var tmp = a; a = b; b = tmp; } if(!result) result = new Array(b.length); for(var i = 0; i < a.length; ++i){ result[i] = (a[i] + b[i])/2; } for(var i = a.length; i < b.length; ++i){ result[i] = b[i]; } return result; } //this function may not care, but the expected matrix format in this project is a list of column vectors. function matrix_transpose(matrix){ if(!matrix) throw "argument to matrix_transpose missing"; var result = []; var dim0 = matrix.length; if(!dim0) return result; var dim1 = matrix[0].length; for(var i = 0; i < dim1; ++i){ var colvector = []; for(var j = 0; j < dim0; ++j){ colvector.push(matrix[j][i]); } result.push(colvector); } return result; } function matrix_mult(a, b){ if(!a) throw "first argument to matrix_mult missing"; if(!b) throw "second argument to matrix_mult missing"; var result = []; var a = matrix_transpose(a); var dim0 = a.length; var dim1 = b.length; for(var i = 0; i < dim1; ++i){ var colvector = []; for(var j = 0; j < dim0; ++j){ colvector.push( vector_dot(a[j], b[i]) ); } result.push(colvector); } return result; } // finds the inverse of a 3 by 3 matrix, returns false if matrix has determinant zero. // function matrix33inv(m){ if(!m) throw "argument to matrix33inv missing"; // the matrix format is a list of column vectors. var a = m[0][0]; var b = m[1][0]; var c = m[2][0]; var d = m[0][1]; var e = m[1][1]; var f = m[2][1]; var g = m[0][2]; var h = m[1][2]; var k = m[2][2]; // [ a b c // d e f // g h k ] var A = e*k - f*h; var B = f*g - d*k; var C = d*h - e*g; var D = h*c - b*k; var E = a*k - c*g; var F = g*b - a*h; var G = b*f - e*c; var H = d*c - a*f; var K = a*e - d*b; var det = (a*A + b*B + c*C); if(det == 0) return false; // the multiplicative inverse of the determinant. var di = 1/det; // the matrix format is a list of column vectors. var result = [[di*A, di*B, di*C], [di*D, di*E, di*F], [di*G, di*H, di*K]]; return result; } // does not check if function is differentiable. function compute_gradient(func, point, error){ if(!func) throw "function argument to compute_gradient missing"; if(!point) throw "point argument to compute_gradient missing"; if(!error) error = 0.00001; // find gradient var otherpoint = point.slice(0); var gradient = new Array(point.length); var pointvalue = func(point); for(var i = 0; i < point.length; ++i){ otherpoint[i] += error; var othervalue = func(otherpoint) gradient[i] = (othervalue - pointvalue) / error; otherpoint[i] -= error; } return gradient; } // // equation at: // http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html // creates a rotation matrix about the given vector. // function vector_rotation(vector, s){ if(!vector) throw "vector argument to vector_rotation missing"; if(s === null || s === undefined) throw "angle argument to vector_rotation missing"; var len = Math.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]); var u = vector[0]/len; var v = vector[1]/len; var w = vector[2]/len; var _cos = Math.cos(s); var _sin = Math.sin(s); var _1mcos = 1 - _cos; return [[u*u*_1mcos + _cos, u*v*_1mcos - w*_sin, u*w*_1mcos + v*_sin], [u*v*_1mcos + w*_sin, v*v*_1mcos + _cos, v*w*_1mcos - u*_sin], [u*w*_1mcos - v*_sin, v*w*_1mcos + u*_sin, w*w*_1mcos + _cos]]; }