// 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) 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]]; }