[Pkg-javascript-commits] [science.js] 51/87: Rename science.vector to science.lin.

bhuvan krishna bhuvan-guest at moszumanska.debian.org
Thu Dec 8 06:11:59 UTC 2016


This is an automated email from the git hooks/post-receive script.

bhuvan-guest pushed a commit to branch master
in repository science.js.

commit 48868457ac1d7c4462605b4ee3ee7c8b53203b73
Author: Jason Davies <jason at jasondavies.com>
Date:   Thu Dec 15 13:03:54 2011 +0000

    Rename science.vector to science.lin.
---
 Makefile                           |  24 +-
 science.js                         | 874 -------------------------------------
 science.lin.js                     | 873 ++++++++++++++++++++++++++++++++++++
 science.lin.min.js                 |   2 +-
 science.min.js                     |   2 +-
 src/{vector => lin}/cross.js       |   2 +-
 src/{vector => lin}/decompose.js   |  28 +-
 src/{vector => lin}/determinant.js |   2 +-
 src/{vector => lin}/dot.js         |   2 +-
 src/{vector => lin}/gaussjordan.js |   2 +-
 src/{vector => lin}/inverse.js     |   4 +-
 src/{vector => lin}/length.js      |   2 +-
 src/{vector => lin}/multiply.js    |   2 +-
 src/lin/normalize.js               |   4 +
 src/{vector => lin}/transpose.js   |   2 +-
 src/vector/normalize.js            |   4 -
 src/vector/vector.js               |   1 -
 test/lin/decompose-test.js         |  24 +
 test/lin/tridag-test.js            |   2 +-
 test/vector/decompose-test.js      |  23 -
 20 files changed, 937 insertions(+), 942 deletions(-)

diff --git a/Makefile b/Makefile
index 3c4eaa7..e686c2c 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,6 @@ all: \
 .INTERMEDIATE science.js: \
 	src/start.js \
 	science.core.js \
-	science.vector.js \
 	src/end.js
 
 science.core.js: \
@@ -26,22 +25,19 @@ science.core.js: \
 	src/core/quadratic.js \
 	src/core/zeroes.js
 
-science.vector.js: \
-	src/vector/vector.js \
-	src/vector/decompose.js \
-	src/vector/cross.js \
-	src/vector/dot.js \
-	src/vector/length.js \
-	src/vector/normalize.js \
-	src/vector/determinant.js \
-	src/vector/gaussjordan.js \
-	src/vector/inverse.js \
-	src/vector/multiply.js \
-	src/vector/transpose.js
-
 science.lin.js: \
 	src/start.js \
 	src/lin/lin.js \
+	src/lin/decompose.js \
+	src/lin/cross.js \
+	src/lin/dot.js \
+	src/lin/length.js \
+	src/lin/normalize.js \
+	src/lin/determinant.js \
+	src/lin/gaussjordan.js \
+	src/lin/inverse.js \
+	src/lin/multiply.js \
+	src/lin/transpose.js \
 	src/lin/tridag.js \
 	src/end.js
 
diff --git a/science.js b/science.js
index 0d0c91b..87293e9 100644
--- a/science.js
+++ b/science.js
@@ -69,878 +69,4 @@ science.zeroes = function(n) {
         this, Array.prototype.slice.call(arguments, 1));
   return a;
 };
-science.vector = {};
-science.vector.decompose = function() {
-
-  function decompose(A) {
-    var n = A.length; // column dimension
-    var V = [],
-        d = [],
-        e = [];
-
-    for (var i = 0; i < n; i++) {
-      V[i] = [];
-      d[i] = [];
-      e[i] = [];
-    }
-
-    var symmetric = true;
-    for (var j = 0; j < n; j++) {
-      for (var i = 0; i < n; i++) {
-        if (A[i][j] !== A[j][i]) {
-          symmetric = false;
-          break;
-        }
-      }
-    }
-
-    if (symmetric) {
-      for (var i = 0; i < n; i++) V[i] = A[i].slice();
-
-      // Tridiagonalize.
-      science_vector_decomposeTred2(d, e, V);
-
-      // Diagonalize.
-      science_vector_decomposeTql2(d, e, V);
-    } else {
-      var H = [];
-      for (var i = 0; i < n; i++) H[i] = A[i].slice();
-
-      // Reduce to Hessenberg form.
-      science_vector_decomposeOrthes(H, V);
-
-      // Reduce Hessenberg to real Schur form.
-      science_vector_decomposeHqr2(d, e, H, V);
-    }
-
-    var D = [];
-    for (var i=0; i<n; i++) {
-      var row = D[i] = [];
-      for (var j=0; j<n; j++) row[j] = i === j ? d[i] : 0;
-      if (e[i] > 0) D[i][i+1] = e[i];
-      else if (e[i] < 0) D[i][i-1] = e[i];
-    }
-    return {D: D, V: V};
-  }
-
-  return decompose;
-};
-
-// Symmetric Householder reduction to tridiagonal form.
-function science_vector_decomposeTred2(d, e, V) {
-  // This is derived from the Algol procedures tred2 by
-  // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
-  // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
-  // Fortran subroutine in EISPACK.
-
-  var n = V.length;
-
-  for (var j = 0; j < n; j++) d[j] = V[n - 1][j];
-
-  // Householder reduction to tridiagonal form.
-  for (var i = n - 1; i > 0; i--) {
-    // Scale to avoid under/overflow.
-
-    var scale = 0,
-        h = 0;
-    for (var k = 0; k < i; k++) { scale = scale + Math.abs(d[k]); }
-    if (scale === 0) {
-      e[i] = d[i-1];
-      for (var j = 0; j < i; j++) {
-        d[j] = V[i-1][j];
-        V[i][j] = 0;
-        V[j][i] = 0;
-      }
-    } else {
-      // Generate Householder vector.
-      for (var k = 0; k < i; k++) {
-        d[k] /= scale;
-        h += d[k] * d[k];
-      }
-      var f = d[i-1];
-      var g = Math.sqrt(h);
-      if (f > 0) g = -g;
-      e[i] = scale * g;
-      h = h - f * g;
-      d[i-1] = f - g;
-      for (var j = 0; j < i; j++) e[j] = 0;
-
-      // Apply similarity transformation to remaining columns.
-
-      for (var j = 0; j < i; j++) {
-        f = d[j];
-        V[j][i] = f;
-        g = e[j] + V[j][j] * f;
-        for (var k = j+1; k <= i-1; k++) {
-          g += V[k][j] * d[k];
-          e[k] += V[k][j] * f;
-        }
-        e[j] = g;
-      }
-      f = 0;
-      for (var j = 0; j < i; j++) {
-        e[j] /= h;
-        f += e[j] * d[j];
-      }
-      var hh = f / (h + h);
-      for (var j = 0; j < i; j++) { e[j] -= hh * d[j]; }
-      for (var j = 0; j < i; j++) {
-        f = d[j];
-        g = e[j];
-        for (var k = j; k <= i-1; k++) { V[k][j] -= (f * e[k] + g * d[k]); }
-        d[j] = V[i-1][j];
-        V[i][j] = 0;
-      }
-    }
-    d[i] = h;
-  }
-
-  // Accumulate transformations.
-  for (var i = 0; i < n - 1; i++) {
-    V[n - 1][i] = V[i][i];
-    V[i][i] = 1.0;
-    var h = d[i+1];
-    if (h != 0) {
-      for (var k = 0; k <= i; k++) { d[k] = V[k][i+1] / h; }
-      for (var j = 0; j <= i; j++) {
-        var g = 0;
-        for (var k = 0; k <= i; k++) { g += V[k][i+1] * V[k][j]; }
-        for (var k = 0; k <= i; k++) { V[k][j] -= g * d[k]; }
-      }
-    }
-    for (var k = 0; k <= i; k++) { V[k][i+1] = 0; }
-  }
-  for (var j = 0; j < n; j++) {
-    d[j] = V[n - 1][j];
-    V[n - 1][j] = 0;
-  }
-  V[n - 1][n - 1] = 1;
-  e[0] = 0;
-}
-
-// Symmetric tridiagonal QL algorithm.
-function science_vector_decomposeTql2(d, e, V) {
-  // This is derived from the Algol procedures tql2, by
-  // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
-  // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
-  // Fortran subroutine in EISPACK.
-
-  var n = V.length;
-
-  for (var i = 1; i < n; i++) { e[i-1] = e[i]; }
-  e[n - 1] = 0;
-
-  var f = 0;
-  var tst1 = 0;
-  var eps = 1e-12;
-  for (var l = 0; l < n; l++) {
-    // Find small subdiagonal element
-    tst1 = Math.max(tst1, Math.abs(d[l]) + Math.abs(e[l]));
-    var m = l;
-    while (m < n) {
-      if (Math.abs(e[m]) <= eps*tst1) { break; }
-      m++;
-    }
-
-    // If m == l, d[l] is an eigenvalue,
-    // otherwise, iterate.
-    if (m > l) {
-      var iter = 0;
-      do {
-        iter++;  // (Could check iteration count here.)
-
-        // Compute implicit shift
-        var g = d[l];
-        var p = (d[l+1] - g) / (2.0 * e[l]);
-        var r = science.hypot(p, 1);
-        if (p < 0) {
-            r = -r;
-        }
-        d[l] = e[l] / (p + r);
-        d[l+1] = e[l] * (p + r);
-        var dl1 = d[l+1];
-        var h = g - d[l];
-        for (var i = l+2; i < n; i++) {
-            d[i] -= h;
-        }
-        f = f + h;
-
-        // Implicit QL transformation.
-        p = d[m];
-        var c = 1.0;
-        var c2 = c;
-        var c3 = c;
-        var el1 = e[l+1];
-        var s = 0;
-        var s2 = 0;
-        for (var i = m-1; i >= l; i--) {
-          c3 = c2;
-          c2 = c;
-          s2 = s;
-          g = c * e[i];
-          h = c * p;
-          r = science.hypot(p,e[i]);
-          e[i+1] = s * r;
-          s = e[i] / r;
-          c = p / r;
-          p = c * d[i] - s * g;
-          d[i+1] = h + s * (c * g + s * d[i]);
-
-          // Accumulate transformation.
-          for (var k = 0; k < n; k++) {
-            h = V[k][i+1];
-            V[k][i+1] = s * V[k][i] + c * h;
-            V[k][i] = c * V[k][i] - s * h;
-          }
-        }
-        p = -s * s2 * c3 * el1 * e[l] / dl1;
-        e[l] = s * p;
-        d[l] = c * p;
-
-        // Check for convergence.
-      } while (Math.abs(e[l]) > eps*tst1);
-    }
-    d[l] = d[l] + f;
-    e[l] = 0;
-  }
-
-  // Sort eigenvalues and corresponding vectors.
-  for (var i = 0; i < n - 1; i++) {
-    var k = i;
-    var p = d[i];
-    for (var j = i+1; j < n; j++) {
-      if (d[j] < p) {
-        k = j;
-        p = d[j];
-      }
-    }
-    if (k != i) {
-      d[k] = d[i];
-      d[i] = p;
-      for (var j = 0; j < n; j++) {
-        p = V[j][i];
-        V[j][i] = V[j][k];
-        V[j][k] = p;
-      }
-    }
-  }
-}
-
-// Nonsymmetric reduction to Hessenberg form.
-function science_vector_decomposeOrthes(H, V) {
-  // This is derived from the Algol procedures orthes and ortran,
-  // by Martin and Wilkinson, Handbook for Auto. Comp.,
-  // Vol.ii-Linear Algebra, and the corresponding
-  // Fortran subroutines in EISPACK.
-
-  var n = H.length;
-  var ort = [];
-
-  var low = 0;
-  var high = n - 1;
-
-  for (var m = low + 1; m < high; m++) {
-    // Scale column.
-    var scale = 0;
-    for (var i = m; i <= high; i++) scale += Math.abs(H[i][m - 1]);
-
-    if (scale !== 0) {
-      // Compute Householder transformation.
-      var h = 0;
-      for (var i = high; i >= m; i--) {
-        ort[i] = H[i][m - 1] / scale;
-        h += ort[i] * ort[i];
-      }
-      var g = Math.sqrt(h);
-      if (ort[m] > 0) { g = -g; }
-      h = h - ort[m] * g;
-      ort[m] = ort[m] - g;
-
-      // Apply Householder similarity transformation
-      // H = (I-u*u'/h)*H*(I-u*u')/h)
-      for (var j = m; j < n; j++) {
-        var f = 0;
-        for (var i = high; i >= m; i--) f += ort[i] * H[i][j];
-        f /= h;
-        for (var i = m; i <= high; i++) H[i][j] -= f * ort[i];
-      }
-
-      for (var i = 0; i <= high; i++) {
-        var f = 0;
-        for (var j = high; j >= m; j--) f += ort[j] * H[i][j];
-        f /= h;
-        for (var j = m; j <= high; j++) H[i][j] -= f * ort[j];
-      }
-      ort[m] = scale * ort[m];
-      H[m][m - 1] = scale * g;
-    }
-  }
-
-  // Accumulate transformations (Algol's ortran).
-  for (var i = 0; i < n; i++) {
-    for (var j = 0; j < n; j++) V[i][j] = i === j ? 1 : 0;
-  }
-
-  for (var m = high-1; m >= low+1; m--) {
-    if (H[m][m - 1] !== 0) {
-      for (var i = m + 1; i <= high; i++) { ort[i] = H[i][m-1]; }
-      for (var j = m; j <= high; j++) {
-        var g = 0;
-        for (var i = m; i <= high; i++) { g += ort[i] * V[i][j]; }
-        // Double division avoids possible underflow
-        g = (g / ort[m]) / H[m][m-1];
-        for (var i = m; i <= high; i++) { V[i][j] += g * ort[i]; }
-      }
-    }
-  }
-}
-
-// Nonsymmetric reduction from Hessenberg to real Schur form.
-function science_vector_decomposeHqr2(d, e, H, V) {
-  // This is derived from the Algol procedure hqr2,
-  // by Martin and Wilkinson, Handbook for Auto. Comp.,
-  // Vol.ii-Linear Algebra, and the corresponding
-  // Fortran subroutine in EISPACK.
-
-  var nn = H.length,
-      n = nn - 1,
-      low = 0,
-      high = nn - 1,
-      eps = 1e-12,
-      exshift = 0,
-      p = 0,
-      q = 0,
-      r = 0,
-      s = 0,
-      z = 0,
-      t,
-      w,
-      x,
-      y;
-
-  // Store roots isolated by balanc and compute matrix norm
-  var norm = 0;
-  for (var i = 0; i < nn; i++) {
-    if (i < low || i > high) {
-      d[i] = H[i][i];
-      e[i] = 0;
-    }
-    for (var j = Math.max(i - 1, 0); j < nn; j++) norm += Math.abs(H[i][j]);
-  }
-
-  // Outer loop over eigenvalue index
-  var iter = 0;
-  while (n >= low) {
-    // Look for single small sub-diagonal element
-    var l = n;
-    while (l > low) {
-      s = Math.abs(H[l - 1][l - 1]) + Math.abs(H[l][l]);
-      if (s === 0) s = norm;
-      if (Math.abs(H[l][l - 1]) < eps * s) break;
-      l--;
-    }
-
-    // Check for convergence
-    // One root found
-    if (l === n) {
-      H[n][n] = H[n][n] + exshift;
-      d[n] = H[n][n];
-      e[n] = 0;
-      n--;
-      iter = 0;
-
-    // Two roots found
-    } else if (l === n - 1) {
-      w = H[n][n - 1] * H[n - 1][n];
-      p = (H[n - 1][n - 1] - H[n][n]) / 2;
-      q = p * p + w;
-      z = Math.sqrt(Math.abs(q));
-      H[n][n] = H[n][n] + exshift;
-      H[n - 1][n - 1] = H[n - 1][n - 1] + exshift;
-      x = H[n][n];
-
-      // Real pair
-      if (q >= 0) {
-        z = p + (p >= 0 ? z : -z);
-        d[n - 1] = x + z;
-        d[n] = d[n - 1];
-        if (z !== 0) d[n] = x - w / z;
-        e[n - 1] = 0;
-        e[n] = 0;
-        x = H[n][n - 1];
-        s = Math.abs(x) + Math.abs(z);
-        p = x / s;
-        q = z / s;
-        r = Math.sqrt(p * p+q * q);
-        p /= r;
-        q /= r;
-
-        // Row modification
-        for (var j = n - 1; j < nn; j++) {
-          z = H[n - 1][j];
-          H[n - 1][j] = q * z + p * H[n][j];
-          H[n][j] = q * H[n][j] - p * z;
-        }
-
-        // Column modification
-        for (var i = 0; i <= n; i++) {
-          z = H[i][n - 1];
-          H[i][n - 1] = q * z + p * H[i][n];
-          H[i][n] = q * H[i][n] - p * z;
-        }
-
-        // Accumulate transformations
-        for (var i = low; i <= high; i++) {
-          z = V[i][n - 1];
-          V[i][n - 1] = q * z + p * V[i][n];
-          V[i][n] = q * V[i][n] - p * z;
-        }
-
-        // Complex pair
-      } else {
-        d[n - 1] = x + p;
-        d[n] = x + p;
-        e[n - 1] = z;
-        e[n] = -z;
-      }
-      n = n - 2;
-      iter = 0;
-
-      // No convergence yet
-    } else {
-
-      // Form shift
-      x = H[n][n];
-      y = 0;
-      w = 0;
-      if (l < n) {
-        y = H[n - 1][n - 1];
-        w = H[n][n - 1] * H[n - 1][n];
-      }
-
-      // Wilkinson's original ad hoc shift
-      if (iter == 10) {
-        exshift += x;
-        for (var i = low; i <= n; i++) {
-          H[i][i] -= x;
-        }
-        s = Math.abs(H[n][n - 1]) + Math.abs(H[n - 1][n-2]);
-        x = y = 0.75 * s;
-        w = -0.4375 * s * s;
-      }
-
-      // MATLAB's new ad hoc shift
-      if (iter == 30) {
-        s = (y - x) / 2.0;
-        s = s * s + w;
-        if (s > 0) {
-          s = Math.sqrt(s);
-          if (y < x) {
-            s = -s;
-          }
-          s = x - w / ((y - x) / 2.0 + s);
-          for (var i = low; i <= n; i++) {
-            H[i][i] -= s;
-          }
-          exshift += s;
-          x = y = w = 0.964;
-        }
-      }
-
-      iter++;   // (Could check iteration count here.)
-
-      // Look for two consecutive small sub-diagonal elements
-      var m = n-2;
-      while (m >= l) {
-        z = H[m][m];
-        r = x - z;
-        s = y - z;
-        p = (r * s - w) / H[m+1][m] + H[m][m+1];
-        q = H[m+1][m+1] - z - r - s;
-        r = H[m+2][m+1];
-        s = Math.abs(p) + Math.abs(q) + Math.abs(r);
-        p = p / s;
-        q = q / s;
-        r = r / s;
-        if (m == l) {
-          break;
-        }
-        if (Math.abs(H[m][m-1]) * (Math.abs(q) + Math.abs(r)) <
-          eps * (Math.abs(p) * (Math.abs(H[m-1][m-1]) + Math.abs(z) +
-          Math.abs(H[m+1][m+1])))) {
-            break;
-        }
-        m--;
-      }
-
-      for (var i = m+2; i <= n; i++) {
-        H[i][i-2] = 0;
-        if (i > m+2) { H[i][i-3] = 0; }
-      }
-
-      // Double QR step involving rows l:n and columns m:n
-      for (var k = m; k <= n - 1; k++) {
-        var notlast = (k != n - 1);
-        if (k != m) {
-          p = H[k][k-1];
-          q = H[k+1][k-1];
-          r = (notlast ? H[k+2][k-1] : 0);
-          x = Math.abs(p) + Math.abs(q) + Math.abs(r);
-          if (x != 0) {
-            p /= x;
-            q /= x;
-            r /= x;
-          }
-        }
-        if (x == 0) { break; }
-        s = Math.sqrt(p * p + q * q + r * r);
-        if (p < 0) { s = -s; }
-        if (s != 0) {
-          if (k != m) H[k][k-1] = -s * x;
-          else if (l != m) H[k][k-1] = -H[k][k-1];
-          p += s;
-          x = p / s;
-          y = q / s;
-          z = r / s;
-          q /= p;
-          r /= p;
-
-          // Row modification
-          for (var j = k; j < nn; j++) {
-            p = H[k][j] + q * H[k+1][j];
-            if (notlast) {
-              p = p + r * H[k+2][j];
-              H[k+2][j] = H[k+2][j] - p * z;
-            }
-            H[k][j] = H[k][j] - p * x;
-            H[k+1][j] = H[k+1][j] - p * y;
-          }
-
-          // Column modification
-          for (var i = 0; i <= Math.min(n,k+3); i++) {
-            p = x * H[i][k] + y * H[i][k+1];
-            if (notlast) {
-              p += z * H[i][k+2];
-              H[i][k+2] = H[i][k+2] - p * r;
-            }
-            H[i][k] = H[i][k] - p;
-            H[i][k+1] = H[i][k+1] - p * q;
-          }
-
-          // Accumulate transformations
-          for (var i = low; i <= high; i++) {
-            p = x * V[i][k] + y * V[i][k+1];
-            if (notlast) {
-              p = p + z * V[i][k+2];
-              V[i][k+2] = V[i][k+2] - p * r;
-            }
-            V[i][k] = V[i][k] - p;
-            V[i][k+1] = V[i][k+1] - p * q;
-          }
-        }  // (s != 0)
-      }  // k loop
-    }  // check convergence
-  }  // while (n >= low)
-
-  // Backsubstitute to find vectors of upper triangular form
-  if (norm == 0) { return; }
-
-  for (n = nn - 1; n >= 0; n--) {
-    p = d[n];
-    q = e[n];
-
-    // Real vector
-    if (q == 0) {
-      var l = n;
-      H[n][n] = 1.0;
-      for (var i = n - 1; i >= 0; i--) {
-        w = H[i][i] - p;
-        r = 0;
-        for (var j = l; j <= n; j++) { r = r + H[i][j] * H[j][n]; }
-        if (e[i] < 0) {
-          z = w;
-          s = r;
-        } else {
-          l = i;
-          if (e[i] == 0) {
-              if (w != 0) {
-                  H[i][n] = -r / w;
-              } else {
-                  H[i][n] = -r / (eps * norm);
-              }
-          } else {
-            // Solve real equations
-            x = H[i][i+1];
-            y = H[i+1][i];
-            q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
-            t = (x * s - z * r) / q;
-            H[i][n] = t;
-            if (Math.abs(x) > Math.abs(z)) {
-              H[i+1][n] = (-r - w * t) / x;
-            } else {
-              H[i+1][n] = (-s - y * t) / z;
-            }
-          }
-
-          // Overflow control
-          t = Math.abs(H[i][n]);
-          if ((eps * t) * t > 1) {
-            for (var j = i; j <= n; j++) H[j][n] = H[j][n] / t;
-          }
-        }
-      }
-    // Complex vector
-    } else if (q < 0) {
-      var l = n - 1;
-
-      // Last vector component imaginary so matrix is triangular
-      if (Math.abs(H[n][n - 1]) > Math.abs(H[n - 1][n])) {
-        H[n - 1][n - 1] = q / H[n][n - 1];
-        H[n - 1][n] = -(H[n][n] - p) / H[n][n - 1];
-      } else {
-        var zz = science_vector_decomposeCdiv(0, -H[n - 1][n], H[n - 1][n - 1] - p, q);
-        H[n - 1][n - 1] = zz[0];
-        H[n - 1][n] = zz[1];
-      }
-      H[n][n - 1] = 0;
-      H[n][n] = 1;
-      for (var i = n-2; i >= 0; i--) {
-        var ra = 0,
-            sa = 0,
-            vr,
-            vi;
-        for (var j = l; j <= n; j++) {
-          ra = ra + H[i][j] * H[j][n - 1];
-          sa = sa + H[i][j] * H[j][n];
-        }
-        w = H[i][i] - p;
-
-        if (e[i] < 0) {
-          z = w;
-          r = ra;
-          s = sa;
-        } else {
-          l = i;
-          if (e[i] == 0) {
-            var zz = science_vector_decomposeCdiv(-ra,-sa,w,q);
-            H[i][n - 1] = zz[0];
-            H[i][n] = zz[1];
-          } else {
-            // Solve complex equations
-            x = H[i][i+1];
-            y = H[i+1][i];
-            vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
-            vi = (d[i] - p) * 2.0 * q;
-            if (vr == 0 & vi == 0) {
-              vr = eps * norm * (Math.abs(w) + Math.abs(q) +
-                Math.abs(x) + Math.abs(y) + Math.abs(z));
-            }
-            var zz = science_vector_decomposeCdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
-            H[i][n - 1] = zz[0];
-            H[i][n] = zz[1];
-            if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
-              H[i+1][n - 1] = (-ra - w * H[i][n - 1] + q * H[i][n]) / x;
-              H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n - 1]) / x;
-            } else {
-              var zz = science_vector_decomposeCdiv(-r-y*H[i][n - 1],-s-y*H[i][n],z,q);
-              H[i+1][n - 1] = zz[0];
-              H[i+1][n] = zz[1];
-            }
-          }
-
-          // Overflow control
-          t = Math.max(Math.abs(H[i][n - 1]),Math.abs(H[i][n]));
-          if ((eps * t) * t > 1) {
-            for (var j = i; j <= n; j++) {
-              H[j][n - 1] = H[j][n - 1] / t;
-              H[j][n] = H[j][n] / t;
-            }
-          }
-        }
-      }
-    }
-  }
-
-  // Vectors of isolated roots
-  for (var i = 0; i < nn; i++) {
-    if (i < low || i > high) {
-      for (var j = i; j < nn; j++) { V[i][j] = H[i][j]; }
-    }
-  }
-
-  // Back transformation to get eigenvectors of original matrix
-  for (var j = nn - 1; j >= low; j--) {
-    for (var i = low; i <= high; i++) {
-      z = 0;
-      for (var k = low; k <= Math.min(j,high); k++) z += V[i][k] * H[k][j];
-      V[i][j] = z;
-    }
-  }
-}
-
-// Complex scalar division.
-function science_vector_decomposeCdiv(xr, xi, yr, yi) {
-  var r, d;
-  if (Math.abs(yr) > Math.abs(yi)) {
-    r = yi / yr;
-    d = yr + r * yi;
-    return [(xr + r * xi) / d, (xi - r * xr) / d];
-  } else {
-    r = yr / yi;
-    d = yi + r * yr;
-    return [(r * xr + xi) / d, (r * xi - xr) / d];
-  }
-}
-science.vector.cross = function(a, b) {
-  // TODO how to handle non-3D vectors?
-  // TODO handle 7D vectors?
-  return [
-    a[1] * b[2] - a[2] * b[1],
-    a[2] * b[0] - a[0] * b[2],
-    a[0] * b[1] - a[1] * b[0]
-  ];
-};
-science.vector.dot = function(a, b) {
-  var s = 0,
-      i = -1,
-      n = Math.min(a.length, b.length);
-  while (++i < n) s += a[i] * b[i];
-  return s;
-};
-science.vector.length = function(p) {
-  return Math.sqrt(science.vector.dot(p, p));
-};
-science.vector.normalize = function(p) {
-  var length = science.vector.length(p);
-  return p.map(function(d) { return d / length; });
-};
-// 4x4 matrix determinant.
-science.vector.determinant = function(matrix) {
-  var m = matrix[0].concat(matrix[1]).concat(matrix[2]).concat(matrix[3]);
-  return (
-    m[12] * m[9]  * m[6]  * m[3]  - m[8] * m[13] * m[6]  * m[3]  -
-    m[12] * m[5]  * m[10] * m[3]  + m[4] * m[13] * m[10] * m[3]  +
-    m[8]  * m[5]  * m[14] * m[3]  - m[4] * m[9]  * m[14] * m[3]  -
-    m[12] * m[9]  * m[2]  * m[7]  + m[8] * m[13] * m[2]  * m[7]  +
-    m[12] * m[1]  * m[10] * m[7]  - m[0] * m[13] * m[10] * m[7]  -
-    m[8]  * m[1]  * m[14] * m[7]  + m[0] * m[9]  * m[14] * m[7]  +
-    m[12] * m[5]  * m[2]  * m[11] - m[4] * m[13] * m[2]  * m[11] -
-    m[12] * m[1]  * m[6]  * m[11] + m[0] * m[13] * m[6]  * m[11] +
-    m[4]  * m[1]  * m[14] * m[11] - m[0] * m[5]  * m[14] * m[11] -
-    m[8]  * m[5]  * m[2]  * m[15] + m[4] * m[9]  * m[2]  * m[15] +
-    m[8]  * m[1]  * m[6]  * m[15] - m[0] * m[9]  * m[6]  * m[15] -
-    m[4]  * m[1]  * m[10] * m[15] + m[0] * m[5]  * m[10] * m[15]);
-};
-// Performs in-place Gauss-Jordan elimination.
-//
-// Based on Jarno Elonen's Python version (public domain):
-// http://elonen.iki.fi/code/misc-notes/python-gaussj/index.html
-science.vector.gaussjordan = function(m, eps) {
-  if (!eps) eps = 1e-10;
-
-  var h = m.length,
-      w = m[0].length,
-      y = -1,
-      y2,
-      x;
-
-  while (++y < h) {
-    var maxrow = y;
-
-    // Find max pivot.
-    y2 = y; while (++y2 < h) {
-      if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y]))
-        maxrow = y2;
-    }
-
-    // Swap.
-    var tmp = m[y];
-    m[y] = m[maxrow];
-    m[maxrow] = tmp;
-
-    // Singular?
-    if (Math.abs(m[y][y]) <= eps) return false;
-
-    // Eliminate column y.
-    y2 = y; while (++y2 < h) {
-      var c = m[y2][y] / m[y][y];
-      x = y - 1; while (++x < w) {
-        m[y2][x] -= m[y][x] * c;
-      }
-    }
-  }
-
-  // Backsubstitute.
-  y = h; while (--y >= 0) {
-    var c = m[y][y];
-    y2 = -1; while (++y2 < y) {
-      x = w; while (--x >= y) {
-        m[y2][x] -=  m[y][x] * m[y2][y] / c;
-      }
-    }
-    m[y][y] /= c;
-    // Normalize row y.
-    x = h - 1; while (++x < w) {
-      m[y][x] /= c;
-    }
-  }
-  return true;
-};
-// Find matrix inverse using Gauss-Jordan.
-science.vector.inverse = function(m) {
-  var n = m.length
-      i = -1;
-
-  // Check if the matrix is square.
-  if (n !== m[0].length) return;
-
-  // Augment with identity matrix I to get AI.
-  m = m.map(function(row, i) {
-    var identity = new Array(n),
-        j = -1;
-    while (++j < n) identity[j] = i === j ? 1 : 0;
-    return row.concat(identity);
-  });
-
-  // Compute IA^-1.
-  science.vector.gaussjordan(m);
-
-  // Remove identity matrix I to get A^-1.
-  while (++i < n) {
-    m[i] = m[i].slice(n);
-  }
-
-  return m;
-};
-science.vector.multiply = function(a, b) {
-  var m = a.length,
-      n = b[0].length,
-      p = b.length,
-      i = -1,
-      j,
-      k;
-  if (p !== a[0].length) throw {"error": "columns(a) != rows(b); " + a[0].length + " != " + p};
-  var ab = new Array(m);
-  while (++i < m) {
-    ab[i] = new Array(n);
-    j = -1; while(++j < n) {
-      var s = 0;
-      k = -1; while (++k < p) s += a[i][k] * b[k][j];
-      ab[i][j] = s;
-    }
-  }
-  return ab;
-};
-science.vector.transpose = function(a) {
-  var m = a.length,
-      n = a[0].length,
-      i = -1,
-      j,
-      b = new Array(n);
-  while (++i < n) {
-    b[i] = new Array(m);
-    j = -1; while (++j < m) b[i][j] = a[j][i];
-  }
-  return b;
-};
 })()
\ No newline at end of file
diff --git a/science.lin.js b/science.lin.js
index cbdc2ac..4626e1b 100644
--- a/science.lin.js
+++ b/science.lin.js
@@ -1,4 +1,877 @@
 (function(){science.lin = {};
+science.lin.decompose = function() {
+
+  function decompose(A) {
+    var n = A.length; // column dimension
+    var V = [],
+        d = [],
+        e = [];
+
+    for (var i = 0; i < n; i++) {
+      V[i] = [];
+      d[i] = [];
+      e[i] = [];
+    }
+
+    var symmetric = true;
+    for (var j = 0; j < n; j++) {
+      for (var i = 0; i < n; i++) {
+        if (A[i][j] !== A[j][i]) {
+          symmetric = false;
+          break;
+        }
+      }
+    }
+
+    if (symmetric) {
+      for (var i = 0; i < n; i++) V[i] = A[i].slice();
+
+      // Tridiagonalize.
+      science_lin_decomposeTred2(d, e, V);
+
+      // Diagonalize.
+      science_lin_decomposeTql2(d, e, V);
+    } else {
+      var H = [];
+      for (var i = 0; i < n; i++) H[i] = A[i].slice();
+
+      // Reduce to Hessenberg form.
+      science_lin_decomposeOrthes(H, V);
+
+      // Reduce Hessenberg to real Schur form.
+      science_lin_decomposeHqr2(d, e, H, V);
+    }
+
+    var D = [];
+    for (var i=0; i<n; i++) {
+      var row = D[i] = [];
+      for (var j=0; j<n; j++) row[j] = i === j ? d[i] : 0;
+      if (e[i] > 0) D[i][i+1] = e[i];
+      else if (e[i] < 0) D[i][i-1] = e[i];
+    }
+    return {D: D, V: V};
+  }
+
+  return decompose;
+};
+
+// Symmetric Householder reduction to tridiagonal form.
+function science_lin_decomposeTred2(d, e, V) {
+  // This is derived from the Algol procedures tred2 by
+  // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+  // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+  // Fortran subroutine in EISPACK.
+
+  var n = V.length;
+
+  for (var j = 0; j < n; j++) d[j] = V[n - 1][j];
+
+  // Householder reduction to tridiagonal form.
+  for (var i = n - 1; i > 0; i--) {
+    // Scale to avoid under/overflow.
+
+    var scale = 0,
+        h = 0;
+    for (var k = 0; k < i; k++) { scale = scale + Math.abs(d[k]); }
+    if (scale === 0) {
+      e[i] = d[i-1];
+      for (var j = 0; j < i; j++) {
+        d[j] = V[i-1][j];
+        V[i][j] = 0;
+        V[j][i] = 0;
+      }
+    } else {
+      // Generate Householder vector.
+      for (var k = 0; k < i; k++) {
+        d[k] /= scale;
+        h += d[k] * d[k];
+      }
+      var f = d[i-1];
+      var g = Math.sqrt(h);
+      if (f > 0) g = -g;
+      e[i] = scale * g;
+      h = h - f * g;
+      d[i-1] = f - g;
+      for (var j = 0; j < i; j++) e[j] = 0;
+
+      // Apply similarity transformation to remaining columns.
+
+      for (var j = 0; j < i; j++) {
+        f = d[j];
+        V[j][i] = f;
+        g = e[j] + V[j][j] * f;
+        for (var k = j+1; k <= i-1; k++) {
+          g += V[k][j] * d[k];
+          e[k] += V[k][j] * f;
+        }
+        e[j] = g;
+      }
+      f = 0;
+      for (var j = 0; j < i; j++) {
+        e[j] /= h;
+        f += e[j] * d[j];
+      }
+      var hh = f / (h + h);
+      for (var j = 0; j < i; j++) { e[j] -= hh * d[j]; }
+      for (var j = 0; j < i; j++) {
+        f = d[j];
+        g = e[j];
+        for (var k = j; k <= i-1; k++) { V[k][j] -= (f * e[k] + g * d[k]); }
+        d[j] = V[i-1][j];
+        V[i][j] = 0;
+      }
+    }
+    d[i] = h;
+  }
+
+  // Accumulate transformations.
+  for (var i = 0; i < n - 1; i++) {
+    V[n - 1][i] = V[i][i];
+    V[i][i] = 1.0;
+    var h = d[i+1];
+    if (h != 0) {
+      for (var k = 0; k <= i; k++) { d[k] = V[k][i+1] / h; }
+      for (var j = 0; j <= i; j++) {
+        var g = 0;
+        for (var k = 0; k <= i; k++) { g += V[k][i+1] * V[k][j]; }
+        for (var k = 0; k <= i; k++) { V[k][j] -= g * d[k]; }
+      }
+    }
+    for (var k = 0; k <= i; k++) { V[k][i+1] = 0; }
+  }
+  for (var j = 0; j < n; j++) {
+    d[j] = V[n - 1][j];
+    V[n - 1][j] = 0;
+  }
+  V[n - 1][n - 1] = 1;
+  e[0] = 0;
+}
+
+// Symmetric tridiagonal QL algorithm.
+function science_lin_decomposeTql2(d, e, V) {
+  // This is derived from the Algol procedures tql2, by
+  // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+  // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+  // Fortran subroutine in EISPACK.
+
+  var n = V.length;
+
+  for (var i = 1; i < n; i++) { e[i-1] = e[i]; }
+  e[n - 1] = 0;
+
+  var f = 0;
+  var tst1 = 0;
+  var eps = 1e-12;
+  for (var l = 0; l < n; l++) {
+    // Find small subdiagonal element
+    tst1 = Math.max(tst1, Math.abs(d[l]) + Math.abs(e[l]));
+    var m = l;
+    while (m < n) {
+      if (Math.abs(e[m]) <= eps*tst1) { break; }
+      m++;
+    }
+
+    // If m == l, d[l] is an eigenvalue,
+    // otherwise, iterate.
+    if (m > l) {
+      var iter = 0;
+      do {
+        iter++;  // (Could check iteration count here.)
+
+        // Compute implicit shift
+        var g = d[l];
+        var p = (d[l+1] - g) / (2.0 * e[l]);
+        var r = science.hypot(p, 1);
+        if (p < 0) {
+            r = -r;
+        }
+        d[l] = e[l] / (p + r);
+        d[l+1] = e[l] * (p + r);
+        var dl1 = d[l+1];
+        var h = g - d[l];
+        for (var i = l+2; i < n; i++) {
+            d[i] -= h;
+        }
+        f = f + h;
+
+        // Implicit QL transformation.
+        p = d[m];
+        var c = 1.0;
+        var c2 = c;
+        var c3 = c;
+        var el1 = e[l+1];
+        var s = 0;
+        var s2 = 0;
+        for (var i = m-1; i >= l; i--) {
+          c3 = c2;
+          c2 = c;
+          s2 = s;
+          g = c * e[i];
+          h = c * p;
+          r = science.hypot(p,e[i]);
+          e[i+1] = s * r;
+          s = e[i] / r;
+          c = p / r;
+          p = c * d[i] - s * g;
+          d[i+1] = h + s * (c * g + s * d[i]);
+
+          // Accumulate transformation.
+          for (var k = 0; k < n; k++) {
+            h = V[k][i+1];
+            V[k][i+1] = s * V[k][i] + c * h;
+            V[k][i] = c * V[k][i] - s * h;
+          }
+        }
+        p = -s * s2 * c3 * el1 * e[l] / dl1;
+        e[l] = s * p;
+        d[l] = c * p;
+
+        // Check for convergence.
+      } while (Math.abs(e[l]) > eps*tst1);
+    }
+    d[l] = d[l] + f;
+    e[l] = 0;
+  }
+
+  // Sort eigenvalues and corresponding vectors.
+  for (var i = 0; i < n - 1; i++) {
+    var k = i;
+    var p = d[i];
+    for (var j = i+1; j < n; j++) {
+      if (d[j] < p) {
+        k = j;
+        p = d[j];
+      }
+    }
+    if (k != i) {
+      d[k] = d[i];
+      d[i] = p;
+      for (var j = 0; j < n; j++) {
+        p = V[j][i];
+        V[j][i] = V[j][k];
+        V[j][k] = p;
+      }
+    }
+  }
+}
+
+// Nonsymmetric reduction to Hessenberg form.
+function science_lin_decomposeOrthes(H, V) {
+  // This is derived from the Algol procedures orthes and ortran,
+  // by Martin and Wilkinson, Handbook for Auto. Comp.,
+  // Vol.ii-Linear Algebra, and the corresponding
+  // Fortran subroutines in EISPACK.
+
+  var n = H.length;
+  var ort = [];
+
+  var low = 0;
+  var high = n - 1;
+
+  for (var m = low + 1; m < high; m++) {
+    // Scale column.
+    var scale = 0;
+    for (var i = m; i <= high; i++) scale += Math.abs(H[i][m - 1]);
+
+    if (scale !== 0) {
+      // Compute Householder transformation.
+      var h = 0;
+      for (var i = high; i >= m; i--) {
+        ort[i] = H[i][m - 1] / scale;
+        h += ort[i] * ort[i];
+      }
+      var g = Math.sqrt(h);
+      if (ort[m] > 0) { g = -g; }
+      h = h - ort[m] * g;
+      ort[m] = ort[m] - g;
+
+      // Apply Householder similarity transformation
+      // H = (I-u*u'/h)*H*(I-u*u')/h)
+      for (var j = m; j < n; j++) {
+        var f = 0;
+        for (var i = high; i >= m; i--) f += ort[i] * H[i][j];
+        f /= h;
+        for (var i = m; i <= high; i++) H[i][j] -= f * ort[i];
+      }
+
+      for (var i = 0; i <= high; i++) {
+        var f = 0;
+        for (var j = high; j >= m; j--) f += ort[j] * H[i][j];
+        f /= h;
+        for (var j = m; j <= high; j++) H[i][j] -= f * ort[j];
+      }
+      ort[m] = scale * ort[m];
+      H[m][m - 1] = scale * g;
+    }
+  }
+
+  // Accumulate transformations (Algol's ortran).
+  for (var i = 0; i < n; i++) {
+    for (var j = 0; j < n; j++) V[i][j] = i === j ? 1 : 0;
+  }
+
+  for (var m = high-1; m >= low+1; m--) {
+    if (H[m][m - 1] !== 0) {
+      for (var i = m + 1; i <= high; i++) { ort[i] = H[i][m-1]; }
+      for (var j = m; j <= high; j++) {
+        var g = 0;
+        for (var i = m; i <= high; i++) { g += ort[i] * V[i][j]; }
+        // Double division avoids possible underflow
+        g = (g / ort[m]) / H[m][m-1];
+        for (var i = m; i <= high; i++) { V[i][j] += g * ort[i]; }
+      }
+    }
+  }
+}
+
+// Nonsymmetric reduction from Hessenberg to real Schur form.
+function science_lin_decomposeHqr2(d, e, H, V) {
+  // This is derived from the Algol procedure hqr2,
+  // by Martin and Wilkinson, Handbook for Auto. Comp.,
+  // Vol.ii-Linear Algebra, and the corresponding
+  // Fortran subroutine in EISPACK.
+
+  var nn = H.length,
+      n = nn - 1,
+      low = 0,
+      high = nn - 1,
+      eps = 1e-12,
+      exshift = 0,
+      p = 0,
+      q = 0,
+      r = 0,
+      s = 0,
+      z = 0,
+      t,
+      w,
+      x,
+      y;
+
+  // Store roots isolated by balanc and compute matrix norm
+  var norm = 0;
+  for (var i = 0; i < nn; i++) {
+    if (i < low || i > high) {
+      d[i] = H[i][i];
+      e[i] = 0;
+    }
+    for (var j = Math.max(i - 1, 0); j < nn; j++) norm += Math.abs(H[i][j]);
+  }
+
+  // Outer loop over eigenvalue index
+  var iter = 0;
+  while (n >= low) {
+    // Look for single small sub-diagonal element
+    var l = n;
+    while (l > low) {
+      s = Math.abs(H[l - 1][l - 1]) + Math.abs(H[l][l]);
+      if (s === 0) s = norm;
+      if (Math.abs(H[l][l - 1]) < eps * s) break;
+      l--;
+    }
+
+    // Check for convergence
+    // One root found
+    if (l === n) {
+      H[n][n] = H[n][n] + exshift;
+      d[n] = H[n][n];
+      e[n] = 0;
+      n--;
+      iter = 0;
+
+    // Two roots found
+    } else if (l === n - 1) {
+      w = H[n][n - 1] * H[n - 1][n];
+      p = (H[n - 1][n - 1] - H[n][n]) / 2;
+      q = p * p + w;
+      z = Math.sqrt(Math.abs(q));
+      H[n][n] = H[n][n] + exshift;
+      H[n - 1][n - 1] = H[n - 1][n - 1] + exshift;
+      x = H[n][n];
+
+      // Real pair
+      if (q >= 0) {
+        z = p + (p >= 0 ? z : -z);
+        d[n - 1] = x + z;
+        d[n] = d[n - 1];
+        if (z !== 0) d[n] = x - w / z;
+        e[n - 1] = 0;
+        e[n] = 0;
+        x = H[n][n - 1];
+        s = Math.abs(x) + Math.abs(z);
+        p = x / s;
+        q = z / s;
+        r = Math.sqrt(p * p+q * q);
+        p /= r;
+        q /= r;
+
+        // Row modification
+        for (var j = n - 1; j < nn; j++) {
+          z = H[n - 1][j];
+          H[n - 1][j] = q * z + p * H[n][j];
+          H[n][j] = q * H[n][j] - p * z;
+        }
+
+        // Column modification
+        for (var i = 0; i <= n; i++) {
+          z = H[i][n - 1];
+          H[i][n - 1] = q * z + p * H[i][n];
+          H[i][n] = q * H[i][n] - p * z;
+        }
+
+        // Accumulate transformations
+        for (var i = low; i <= high; i++) {
+          z = V[i][n - 1];
+          V[i][n - 1] = q * z + p * V[i][n];
+          V[i][n] = q * V[i][n] - p * z;
+        }
+
+        // Complex pair
+      } else {
+        d[n - 1] = x + p;
+        d[n] = x + p;
+        e[n - 1] = z;
+        e[n] = -z;
+      }
+      n = n - 2;
+      iter = 0;
+
+      // No convergence yet
+    } else {
+
+      // Form shift
+      x = H[n][n];
+      y = 0;
+      w = 0;
+      if (l < n) {
+        y = H[n - 1][n - 1];
+        w = H[n][n - 1] * H[n - 1][n];
+      }
+
+      // Wilkinson's original ad hoc shift
+      if (iter == 10) {
+        exshift += x;
+        for (var i = low; i <= n; i++) {
+          H[i][i] -= x;
+        }
+        s = Math.abs(H[n][n - 1]) + Math.abs(H[n - 1][n-2]);
+        x = y = 0.75 * s;
+        w = -0.4375 * s * s;
+      }
+
+      // MATLAB's new ad hoc shift
+      if (iter == 30) {
+        s = (y - x) / 2.0;
+        s = s * s + w;
+        if (s > 0) {
+          s = Math.sqrt(s);
+          if (y < x) {
+            s = -s;
+          }
+          s = x - w / ((y - x) / 2.0 + s);
+          for (var i = low; i <= n; i++) {
+            H[i][i] -= s;
+          }
+          exshift += s;
+          x = y = w = 0.964;
+        }
+      }
+
+      iter++;   // (Could check iteration count here.)
+
+      // Look for two consecutive small sub-diagonal elements
+      var m = n-2;
+      while (m >= l) {
+        z = H[m][m];
+        r = x - z;
+        s = y - z;
+        p = (r * s - w) / H[m+1][m] + H[m][m+1];
+        q = H[m+1][m+1] - z - r - s;
+        r = H[m+2][m+1];
+        s = Math.abs(p) + Math.abs(q) + Math.abs(r);
+        p = p / s;
+        q = q / s;
+        r = r / s;
+        if (m == l) {
+          break;
+        }
+        if (Math.abs(H[m][m-1]) * (Math.abs(q) + Math.abs(r)) <
+          eps * (Math.abs(p) * (Math.abs(H[m-1][m-1]) + Math.abs(z) +
+          Math.abs(H[m+1][m+1])))) {
+            break;
+        }
+        m--;
+      }
+
+      for (var i = m+2; i <= n; i++) {
+        H[i][i-2] = 0;
+        if (i > m+2) { H[i][i-3] = 0; }
+      }
+
+      // Double QR step involving rows l:n and columns m:n
+      for (var k = m; k <= n - 1; k++) {
+        var notlast = (k != n - 1);
+        if (k != m) {
+          p = H[k][k-1];
+          q = H[k+1][k-1];
+          r = (notlast ? H[k+2][k-1] : 0);
+          x = Math.abs(p) + Math.abs(q) + Math.abs(r);
+          if (x != 0) {
+            p /= x;
+            q /= x;
+            r /= x;
+          }
+        }
+        if (x == 0) { break; }
+        s = Math.sqrt(p * p + q * q + r * r);
+        if (p < 0) { s = -s; }
+        if (s != 0) {
+          if (k != m) H[k][k-1] = -s * x;
+          else if (l != m) H[k][k-1] = -H[k][k-1];
+          p += s;
+          x = p / s;
+          y = q / s;
+          z = r / s;
+          q /= p;
+          r /= p;
+
+          // Row modification
+          for (var j = k; j < nn; j++) {
+            p = H[k][j] + q * H[k+1][j];
+            if (notlast) {
+              p = p + r * H[k+2][j];
+              H[k+2][j] = H[k+2][j] - p * z;
+            }
+            H[k][j] = H[k][j] - p * x;
+            H[k+1][j] = H[k+1][j] - p * y;
+          }
+
+          // Column modification
+          for (var i = 0; i <= Math.min(n,k+3); i++) {
+            p = x * H[i][k] + y * H[i][k+1];
+            if (notlast) {
+              p += z * H[i][k+2];
+              H[i][k+2] = H[i][k+2] - p * r;
+            }
+            H[i][k] = H[i][k] - p;
+            H[i][k+1] = H[i][k+1] - p * q;
+          }
+
+          // Accumulate transformations
+          for (var i = low; i <= high; i++) {
+            p = x * V[i][k] + y * V[i][k+1];
+            if (notlast) {
+              p = p + z * V[i][k+2];
+              V[i][k+2] = V[i][k+2] - p * r;
+            }
+            V[i][k] = V[i][k] - p;
+            V[i][k+1] = V[i][k+1] - p * q;
+          }
+        }  // (s != 0)
+      }  // k loop
+    }  // check convergence
+  }  // while (n >= low)
+
+  // Backsubstitute to find vectors of upper triangular form
+  if (norm == 0) { return; }
+
+  for (n = nn - 1; n >= 0; n--) {
+    p = d[n];
+    q = e[n];
+
+    // Real vector
+    if (q == 0) {
+      var l = n;
+      H[n][n] = 1.0;
+      for (var i = n - 1; i >= 0; i--) {
+        w = H[i][i] - p;
+        r = 0;
+        for (var j = l; j <= n; j++) { r = r + H[i][j] * H[j][n]; }
+        if (e[i] < 0) {
+          z = w;
+          s = r;
+        } else {
+          l = i;
+          if (e[i] == 0) {
+              if (w != 0) {
+                  H[i][n] = -r / w;
+              } else {
+                  H[i][n] = -r / (eps * norm);
+              }
+          } else {
+            // Solve real equations
+            x = H[i][i+1];
+            y = H[i+1][i];
+            q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
+            t = (x * s - z * r) / q;
+            H[i][n] = t;
+            if (Math.abs(x) > Math.abs(z)) {
+              H[i+1][n] = (-r - w * t) / x;
+            } else {
+              H[i+1][n] = (-s - y * t) / z;
+            }
+          }
+
+          // Overflow control
+          t = Math.abs(H[i][n]);
+          if ((eps * t) * t > 1) {
+            for (var j = i; j <= n; j++) H[j][n] = H[j][n] / t;
+          }
+        }
+      }
+    // Complex vector
+    } else if (q < 0) {
+      var l = n - 1;
+
+      // Last vector component imaginary so matrix is triangular
+      if (Math.abs(H[n][n - 1]) > Math.abs(H[n - 1][n])) {
+        H[n - 1][n - 1] = q / H[n][n - 1];
+        H[n - 1][n] = -(H[n][n] - p) / H[n][n - 1];
+      } else {
+        var zz = science_lin_decomposeCdiv(0, -H[n - 1][n], H[n - 1][n - 1] - p, q);
+        H[n - 1][n - 1] = zz[0];
+        H[n - 1][n] = zz[1];
+      }
+      H[n][n - 1] = 0;
+      H[n][n] = 1;
+      for (var i = n-2; i >= 0; i--) {
+        var ra = 0,
+            sa = 0,
+            vr,
+            vi;
+        for (var j = l; j <= n; j++) {
+          ra = ra + H[i][j] * H[j][n - 1];
+          sa = sa + H[i][j] * H[j][n];
+        }
+        w = H[i][i] - p;
+
+        if (e[i] < 0) {
+          z = w;
+          r = ra;
+          s = sa;
+        } else {
+          l = i;
+          if (e[i] == 0) {
+            var zz = science_lin_decomposeCdiv(-ra,-sa,w,q);
+            H[i][n - 1] = zz[0];
+            H[i][n] = zz[1];
+          } else {
+            // Solve complex equations
+            x = H[i][i+1];
+            y = H[i+1][i];
+            vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
+            vi = (d[i] - p) * 2.0 * q;
+            if (vr == 0 & vi == 0) {
+              vr = eps * norm * (Math.abs(w) + Math.abs(q) +
+                Math.abs(x) + Math.abs(y) + Math.abs(z));
+            }
+            var zz = science_lin_decomposeCdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+            H[i][n - 1] = zz[0];
+            H[i][n] = zz[1];
+            if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
+              H[i+1][n - 1] = (-ra - w * H[i][n - 1] + q * H[i][n]) / x;
+              H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n - 1]) / x;
+            } else {
+              var zz = science_lin_decomposeCdiv(-r-y*H[i][n - 1],-s-y*H[i][n],z,q);
+              H[i+1][n - 1] = zz[0];
+              H[i+1][n] = zz[1];
+            }
+          }
+
+          // Overflow control
+          t = Math.max(Math.abs(H[i][n - 1]),Math.abs(H[i][n]));
+          if ((eps * t) * t > 1) {
+            for (var j = i; j <= n; j++) {
+              H[j][n - 1] = H[j][n - 1] / t;
+              H[j][n] = H[j][n] / t;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // Vectors of isolated roots
+  for (var i = 0; i < nn; i++) {
+    if (i < low || i > high) {
+      for (var j = i; j < nn; j++) { V[i][j] = H[i][j]; }
+    }
+  }
+
+  // Back transformation to get eigenvectors of original matrix
+  for (var j = nn - 1; j >= low; j--) {
+    for (var i = low; i <= high; i++) {
+      z = 0;
+      for (var k = low; k <= Math.min(j,high); k++) z += V[i][k] * H[k][j];
+      V[i][j] = z;
+    }
+  }
+}
+
+// Complex scalar division.
+function science_lin_decomposeCdiv(xr, xi, yr, yi) {
+  var r, d;
+  if (Math.abs(yr) > Math.abs(yi)) {
+    r = yi / yr;
+    d = yr + r * yi;
+    return [(xr + r * xi) / d, (xi - r * xr) / d];
+  } else {
+    r = yr / yi;
+    d = yi + r * yr;
+    return [(r * xr + xi) / d, (r * xi - xr) / d];
+  }
+}
+science.lin.cross = function(a, b) {
+  // TODO how to handle non-3D vectors?
+  // TODO handle 7D vectors?
+  return [
+    a[1] * b[2] - a[2] * b[1],
+    a[2] * b[0] - a[0] * b[2],
+    a[0] * b[1] - a[1] * b[0]
+  ];
+};
+science.lin.dot = function(a, b) {
+  var s = 0,
+      i = -1,
+      n = Math.min(a.length, b.length);
+  while (++i < n) s += a[i] * b[i];
+  return s;
+};
+science.lin.length = function(p) {
+  return Math.sqrt(science.vector.dot(p, p));
+};
+science.lin.normalize = function(p) {
+  var length = science.lin.length(p);
+  return p.map(function(d) { return d / length; });
+};
+// 4x4 matrix determinant.
+science.lin.determinant = function(matrix) {
+  var m = matrix[0].concat(matrix[1]).concat(matrix[2]).concat(matrix[3]);
+  return (
+    m[12] * m[9]  * m[6]  * m[3]  - m[8] * m[13] * m[6]  * m[3]  -
+    m[12] * m[5]  * m[10] * m[3]  + m[4] * m[13] * m[10] * m[3]  +
+    m[8]  * m[5]  * m[14] * m[3]  - m[4] * m[9]  * m[14] * m[3]  -
+    m[12] * m[9]  * m[2]  * m[7]  + m[8] * m[13] * m[2]  * m[7]  +
+    m[12] * m[1]  * m[10] * m[7]  - m[0] * m[13] * m[10] * m[7]  -
+    m[8]  * m[1]  * m[14] * m[7]  + m[0] * m[9]  * m[14] * m[7]  +
+    m[12] * m[5]  * m[2]  * m[11] - m[4] * m[13] * m[2]  * m[11] -
+    m[12] * m[1]  * m[6]  * m[11] + m[0] * m[13] * m[6]  * m[11] +
+    m[4]  * m[1]  * m[14] * m[11] - m[0] * m[5]  * m[14] * m[11] -
+    m[8]  * m[5]  * m[2]  * m[15] + m[4] * m[9]  * m[2]  * m[15] +
+    m[8]  * m[1]  * m[6]  * m[15] - m[0] * m[9]  * m[6]  * m[15] -
+    m[4]  * m[1]  * m[10] * m[15] + m[0] * m[5]  * m[10] * m[15]);
+};
+// Performs in-place Gauss-Jordan elimination.
+//
+// Based on Jarno Elonen's Python version (public domain):
+// http://elonen.iki.fi/code/misc-notes/python-gaussj/index.html
+science.lin.gaussjordan = function(m, eps) {
+  if (!eps) eps = 1e-10;
+
+  var h = m.length,
+      w = m[0].length,
+      y = -1,
+      y2,
+      x;
+
+  while (++y < h) {
+    var maxrow = y;
+
+    // Find max pivot.
+    y2 = y; while (++y2 < h) {
+      if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y]))
+        maxrow = y2;
+    }
+
+    // Swap.
+    var tmp = m[y];
+    m[y] = m[maxrow];
+    m[maxrow] = tmp;
+
+    // Singular?
+    if (Math.abs(m[y][y]) <= eps) return false;
+
+    // Eliminate column y.
+    y2 = y; while (++y2 < h) {
+      var c = m[y2][y] / m[y][y];
+      x = y - 1; while (++x < w) {
+        m[y2][x] -= m[y][x] * c;
+      }
+    }
+  }
+
+  // Backsubstitute.
+  y = h; while (--y >= 0) {
+    var c = m[y][y];
+    y2 = -1; while (++y2 < y) {
+      x = w; while (--x >= y) {
+        m[y2][x] -=  m[y][x] * m[y2][y] / c;
+      }
+    }
+    m[y][y] /= c;
+    // Normalize row y.
+    x = h - 1; while (++x < w) {
+      m[y][x] /= c;
+    }
+  }
+  return true;
+};
+// Find matrix inverse using Gauss-Jordan.
+science.lin.inverse = function(m) {
+  var n = m.length
+      i = -1;
+
+  // Check if the matrix is square.
+  if (n !== m[0].length) return;
+
+  // Augment with identity matrix I to get AI.
+  m = m.map(function(row, i) {
+    var identity = new Array(n),
+        j = -1;
+    while (++j < n) identity[j] = i === j ? 1 : 0;
+    return row.concat(identity);
+  });
+
+  // Compute IA^-1.
+  science.lin.gaussjordan(m);
+
+  // Remove identity matrix I to get A^-1.
+  while (++i < n) {
+    m[i] = m[i].slice(n);
+  }
+
+  return m;
+};
+science.lin.multiply = function(a, b) {
+  var m = a.length,
+      n = b[0].length,
+      p = b.length,
+      i = -1,
+      j,
+      k;
+  if (p !== a[0].length) throw {"error": "columns(a) != rows(b); " + a[0].length + " != " + p};
+  var ab = new Array(m);
+  while (++i < m) {
+    ab[i] = new Array(n);
+    j = -1; while(++j < n) {
+      var s = 0;
+      k = -1; while (++k < p) s += a[i][k] * b[k][j];
+      ab[i][j] = s;
+    }
+  }
+  return ab;
+};
+science.lin.transpose = function(a) {
+  var m = a.length,
+      n = a[0].length,
+      i = -1,
+      j,
+      b = new Array(n);
+  while (++i < n) {
+    b[i] = new Array(m);
+    j = -1; while (++j < m) b[i][j] = a[j][i];
+  }
+  return b;
+};
 /**
  * Solves tridiagonal systems of linear equations.
  *
diff --git a/science.lin.min.js b/science.lin.min.js
index 734bfa6..823c921 100644
--- a/science.lin.min.js
+++ b/science.lin.min.js
@@ -1 +1 @@
-(function(){science.lin={},science.lin.tridag=function(a,b,c,d,e,f){var g,h;for(g=1;g<f;g++)h=a[g]/b[g-1],b[g]-=h*c[g-1],d[g]-=h*d[g-1];e[f-1]=d[f-1]/b[f-1];for(g=f-2;g>=0;g--)e[g]=(d[g]-c[g]*e[g+1])/b[g]}})();
\ No newline at end of file
+(function(){function a(a,b,c){var d=c.length;for(var e=0;e<d;e++)a[e]=c[d-1][e];for(var f=d-1;f>0;f--){var g=0,h=0;for(var i=0;i<f;i++)g+=Math.abs(a[i]);if(g===0){b[f]=a[f-1];for(var e=0;e<f;e++)a[e]=c[f-1][e],c[f][e]=0,c[e][f]=0}else{for(var i=0;i<f;i++)a[i]/=g,h+=a[i]*a[i];var j=a[f-1],k=Math.sqrt(h);j>0&&(k=-k),b[f]=g*k,h-=j*k,a[f-1]=j-k;for(var e=0;e<f;e++)b[e]=0;for(var e=0;e<f;e++){j=a[e],c[e][f]=j,k=b[e]+c[e][e]*j;for(var i=e+1;i<=f-1;i++)k+=c[i][e]*a[i],b[i]+=c[i][e]*j;b[e]=k}j=0 [...]
\ No newline at end of file
diff --git a/science.min.js b/science.min.js
index b7defd6..a9473ba 100644
--- a/science.min.js
+++ b/science.min.js
@@ -1 +1 @@
-(function(){function a(a,b,c){var d=c.length;for(var e=0;e<d;e++)a[e]=c[d-1][e];for(var f=d-1;f>0;f--){var g=0,h=0;for(var i=0;i<f;i++)g+=Math.abs(a[i]);if(g===0){b[f]=a[f-1];for(var e=0;e<f;e++)a[e]=c[f-1][e],c[f][e]=0,c[e][f]=0}else{for(var i=0;i<f;i++)a[i]/=g,h+=a[i]*a[i];var j=a[f-1],k=Math.sqrt(h);j>0&&(k=-k),b[f]=g*k,h-=j*k,a[f-1]=j-k;for(var e=0;e<f;e++)b[e]=0;for(var e=0;e<f;e++){j=a[e],c[e][f]=j,k=b[e]+c[e][e]*j;for(var i=e+1;i<=f-1;i++)k+=c[i][e]*a[i],b[i]+=c[i][e]*j;b[e]=k}j=0 [...]
\ No newline at end of file
+(function(){science={version:"1.7.1"},science.ascending=function(a,b){return a-b},science.EULER=.5772156649015329,science.expm1=function(a){return a<1e-5&&a>-0.00001?a+.5*a*a:Math.exp(a)-1},science.functor=function(a){return typeof a=="function"?a:function(){return a}},science.hypot=function(a,b){a=Math.abs(a),b=Math.abs(b);var c,d;a>b?(c=a,d=b):(c=b,d=a);var e=d/c;return c*Math.sqrt(1+e*e)},science.quadratic=function(){function b(b,c,d){var e=c*c-4*b*d;return e>0?(e=Math.sqrt(e)/(2*b),a [...]
\ No newline at end of file
diff --git a/src/vector/cross.js b/src/lin/cross.js
similarity index 81%
rename from src/vector/cross.js
rename to src/lin/cross.js
index 97cd71f..7620260 100644
--- a/src/vector/cross.js
+++ b/src/lin/cross.js
@@ -1,4 +1,4 @@
-science.vector.cross = function(a, b) {
+science.lin.cross = function(a, b) {
   // TODO how to handle non-3D vectors?
   // TODO handle 7D vectors?
   return [
diff --git a/src/vector/decompose.js b/src/lin/decompose.js
similarity index 95%
rename from src/vector/decompose.js
rename to src/lin/decompose.js
index 8e312b9..c2d7d3d 100644
--- a/src/vector/decompose.js
+++ b/src/lin/decompose.js
@@ -1,4 +1,4 @@
-science.vector.decompose = function() {
+science.lin.decompose = function() {
 
   function decompose(A) {
     var n = A.length; // column dimension
@@ -26,19 +26,19 @@ science.vector.decompose = function() {
       for (var i = 0; i < n; i++) V[i] = A[i].slice();
 
       // Tridiagonalize.
-      science_vector_decomposeTred2(d, e, V);
+      science_lin_decomposeTred2(d, e, V);
 
       // Diagonalize.
-      science_vector_decomposeTql2(d, e, V);
+      science_lin_decomposeTql2(d, e, V);
     } else {
       var H = [];
       for (var i = 0; i < n; i++) H[i] = A[i].slice();
 
       // Reduce to Hessenberg form.
-      science_vector_decomposeOrthes(H, V);
+      science_lin_decomposeOrthes(H, V);
 
       // Reduce Hessenberg to real Schur form.
-      science_vector_decomposeHqr2(d, e, H, V);
+      science_lin_decomposeHqr2(d, e, H, V);
     }
 
     var D = [];
@@ -55,7 +55,7 @@ science.vector.decompose = function() {
 };
 
 // Symmetric Householder reduction to tridiagonal form.
-function science_vector_decomposeTred2(d, e, V) {
+function science_lin_decomposeTred2(d, e, V) {
   // This is derived from the Algol procedures tred2 by
   // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
   // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
@@ -147,7 +147,7 @@ function science_vector_decomposeTred2(d, e, V) {
 }
 
 // Symmetric tridiagonal QL algorithm.
-function science_vector_decomposeTql2(d, e, V) {
+function science_lin_decomposeTql2(d, e, V) {
   // This is derived from the Algol procedures tql2, by
   // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
   // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
@@ -255,7 +255,7 @@ function science_vector_decomposeTql2(d, e, V) {
 }
 
 // Nonsymmetric reduction to Hessenberg form.
-function science_vector_decomposeOrthes(H, V) {
+function science_lin_decomposeOrthes(H, V) {
   // This is derived from the Algol procedures orthes and ortran,
   // by Martin and Wilkinson, Handbook for Auto. Comp.,
   // Vol.ii-Linear Algebra, and the corresponding
@@ -324,7 +324,7 @@ function science_vector_decomposeOrthes(H, V) {
 }
 
 // Nonsymmetric reduction from Hessenberg to real Schur form.
-function science_vector_decomposeHqr2(d, e, H, V) {
+function science_lin_decomposeHqr2(d, e, H, V) {
   // This is derived from the Algol procedure hqr2,
   // by Martin and Wilkinson, Handbook for Auto. Comp.,
   // Vol.ii-Linear Algebra, and the corresponding
@@ -626,7 +626,7 @@ function science_vector_decomposeHqr2(d, e, H, V) {
         H[n - 1][n - 1] = q / H[n][n - 1];
         H[n - 1][n] = -(H[n][n] - p) / H[n][n - 1];
       } else {
-        var zz = science_vector_decomposeCdiv(0, -H[n - 1][n], H[n - 1][n - 1] - p, q);
+        var zz = science_lin_decomposeCdiv(0, -H[n - 1][n], H[n - 1][n - 1] - p, q);
         H[n - 1][n - 1] = zz[0];
         H[n - 1][n] = zz[1];
       }
@@ -650,7 +650,7 @@ function science_vector_decomposeHqr2(d, e, H, V) {
         } else {
           l = i;
           if (e[i] == 0) {
-            var zz = science_vector_decomposeCdiv(-ra,-sa,w,q);
+            var zz = science_lin_decomposeCdiv(-ra,-sa,w,q);
             H[i][n - 1] = zz[0];
             H[i][n] = zz[1];
           } else {
@@ -663,14 +663,14 @@ function science_vector_decomposeHqr2(d, e, H, V) {
               vr = eps * norm * (Math.abs(w) + Math.abs(q) +
                 Math.abs(x) + Math.abs(y) + Math.abs(z));
             }
-            var zz = science_vector_decomposeCdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+            var zz = science_lin_decomposeCdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
             H[i][n - 1] = zz[0];
             H[i][n] = zz[1];
             if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
               H[i+1][n - 1] = (-ra - w * H[i][n - 1] + q * H[i][n]) / x;
               H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n - 1]) / x;
             } else {
-              var zz = science_vector_decomposeCdiv(-r-y*H[i][n - 1],-s-y*H[i][n],z,q);
+              var zz = science_lin_decomposeCdiv(-r-y*H[i][n - 1],-s-y*H[i][n],z,q);
               H[i+1][n - 1] = zz[0];
               H[i+1][n] = zz[1];
             }
@@ -707,7 +707,7 @@ function science_vector_decomposeHqr2(d, e, H, V) {
 }
 
 // Complex scalar division.
-function science_vector_decomposeCdiv(xr, xi, yr, yi) {
+function science_lin_decomposeCdiv(xr, xi, yr, yi) {
   var r, d;
   if (Math.abs(yr) > Math.abs(yi)) {
     r = yi / yr;
diff --git a/src/vector/determinant.js b/src/lin/determinant.js
similarity index 95%
rename from src/vector/determinant.js
rename to src/lin/determinant.js
index b79e76a..3e72aa5 100644
--- a/src/vector/determinant.js
+++ b/src/lin/determinant.js
@@ -1,5 +1,5 @@
 // 4x4 matrix determinant.
-science.vector.determinant = function(matrix) {
+science.lin.determinant = function(matrix) {
   var m = matrix[0].concat(matrix[1]).concat(matrix[2]).concat(matrix[3]);
   return (
     m[12] * m[9]  * m[6]  * m[3]  - m[8] * m[13] * m[6]  * m[3]  -
diff --git a/src/vector/dot.js b/src/lin/dot.js
similarity index 75%
rename from src/vector/dot.js
rename to src/lin/dot.js
index 74dfd00..81a6681 100644
--- a/src/vector/dot.js
+++ b/src/lin/dot.js
@@ -1,4 +1,4 @@
-science.vector.dot = function(a, b) {
+science.lin.dot = function(a, b) {
   var s = 0,
       i = -1,
       n = Math.min(a.length, b.length);
diff --git a/src/vector/gaussjordan.js b/src/lin/gaussjordan.js
similarity index 95%
rename from src/vector/gaussjordan.js
rename to src/lin/gaussjordan.js
index 08a8ca1..a7ebd40 100644
--- a/src/vector/gaussjordan.js
+++ b/src/lin/gaussjordan.js
@@ -2,7 +2,7 @@
 //
 // Based on Jarno Elonen's Python version (public domain):
 // http://elonen.iki.fi/code/misc-notes/python-gaussj/index.html
-science.vector.gaussjordan = function(m, eps) {
+science.lin.gaussjordan = function(m, eps) {
   if (!eps) eps = 1e-10;
 
   var h = m.length,
diff --git a/src/vector/inverse.js b/src/lin/inverse.js
similarity index 87%
rename from src/vector/inverse.js
rename to src/lin/inverse.js
index 0a8bb5e..6a87045 100644
--- a/src/vector/inverse.js
+++ b/src/lin/inverse.js
@@ -1,5 +1,5 @@
 // Find matrix inverse using Gauss-Jordan.
-science.vector.inverse = function(m) {
+science.lin.inverse = function(m) {
   var n = m.length
       i = -1;
 
@@ -15,7 +15,7 @@ science.vector.inverse = function(m) {
   });
 
   // Compute IA^-1.
-  science.vector.gaussjordan(m);
+  science.lin.gaussjordan(m);
 
   // Remove identity matrix I to get A^-1.
   while (++i < n) {
diff --git a/src/vector/length.js b/src/lin/length.js
similarity index 56%
rename from src/vector/length.js
rename to src/lin/length.js
index 49618f5..2ed5b56 100644
--- a/src/vector/length.js
+++ b/src/lin/length.js
@@ -1,3 +1,3 @@
-science.vector.length = function(p) {
+science.lin.length = function(p) {
   return Math.sqrt(science.vector.dot(p, p));
 };
diff --git a/src/vector/multiply.js b/src/lin/multiply.js
similarity index 90%
rename from src/vector/multiply.js
rename to src/lin/multiply.js
index dc29173..2917110 100644
--- a/src/vector/multiply.js
+++ b/src/lin/multiply.js
@@ -1,4 +1,4 @@
-science.vector.multiply = function(a, b) {
+science.lin.multiply = function(a, b) {
   var m = a.length,
       n = b[0].length,
       p = b.length,
diff --git a/src/lin/normalize.js b/src/lin/normalize.js
new file mode 100644
index 0000000..3389aca
--- /dev/null
+++ b/src/lin/normalize.js
@@ -0,0 +1,4 @@
+science.lin.normalize = function(p) {
+  var length = science.lin.length(p);
+  return p.map(function(d) { return d / length; });
+};
diff --git a/src/vector/transpose.js b/src/lin/transpose.js
similarity index 83%
rename from src/vector/transpose.js
rename to src/lin/transpose.js
index 48a61db..fa7e47d 100644
--- a/src/vector/transpose.js
+++ b/src/lin/transpose.js
@@ -1,4 +1,4 @@
-science.vector.transpose = function(a) {
+science.lin.transpose = function(a) {
   var m = a.length,
       n = a[0].length,
       i = -1,
diff --git a/src/vector/normalize.js b/src/vector/normalize.js
deleted file mode 100644
index 3f6bc36..0000000
--- a/src/vector/normalize.js
+++ /dev/null
@@ -1,4 +0,0 @@
-science.vector.normalize = function(p) {
-  var length = science.vector.length(p);
-  return p.map(function(d) { return d / length; });
-};
diff --git a/src/vector/vector.js b/src/vector/vector.js
deleted file mode 100644
index fe140eb..0000000
--- a/src/vector/vector.js
+++ /dev/null
@@ -1 +0,0 @@
-science.vector = {};
diff --git a/test/lin/decompose-test.js b/test/lin/decompose-test.js
new file mode 100644
index 0000000..cd8f965
--- /dev/null
+++ b/test/lin/decompose-test.js
@@ -0,0 +1,24 @@
+require("../../science");
+require("../../science.lin");
+
+var vows = require("vows"),
+    assert = require("assert");
+
+var suite = vows.describe("science.lin.decompose");
+
+suite.addBatch({
+  "decompose": {
+    topic: science.lin.decompose,
+    "symmetric": function(decompose) {
+      var A = [[1, 1, 1], [1, 2, 3], [1, 3, 6]],
+          result = decompose(A);
+      assert.inDelta(
+        science.lin.multiply(A, result.V),
+        science.lin.multiply(result.V, result.D),
+        1e-6
+      );
+    }
+  }
+});
+
+suite.export(module);
diff --git a/test/lin/tridag-test.js b/test/lin/tridag-test.js
index ed04362..a2e43d2 100644
--- a/test/lin/tridag-test.js
+++ b/test/lin/tridag-test.js
@@ -28,7 +28,7 @@ suite.addBatch({
         if (i > 0) matrix[i - 1][i] = a[i];
         if (i < n - 1) matrix[i + 1][i] = c[i];
       }
-      var result = science.vector.multiply(matrix, x.map(function(d) { return [d]; }));
+      var result = science.lin.multiply(matrix, x.map(function(d) { return [d]; }));
       var epsilon = 1e-12;
       for (var i=0; i<n; i++) {
         assert.isTrue(result[i] - d[i] < epsilon);
diff --git a/test/vector/decompose-test.js b/test/vector/decompose-test.js
deleted file mode 100644
index 334da3d..0000000
--- a/test/vector/decompose-test.js
+++ /dev/null
@@ -1,23 +0,0 @@
-require("../../science");
-
-var vows = require("vows"),
-    assert = require("assert");
-
-var suite = vows.describe("science.vector.decompose");
-
-suite.addBatch({
-  "decompose": {
-    "symmetric": function() {
-      var decompose = science.vector.decompose();
-      var A = [[1, 1, 1], [1, 2, 3], [1, 3, 6]];
-      var result = decompose(A);
-      assert.inDelta(
-        science.vector.multiply(A, result.V),
-        science.vector.multiply(result.V, result.D),
-        1e-6
-      );
-    }
-  }
-});
-
-suite.export(module);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/science.js.git



More information about the Pkg-javascript-commits mailing list