toolkit/javascript/d3/lib/science/science.js
changeset 47 c0b4a8b5a012
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolkit/javascript/d3/lib/science/science.js	Thu Apr 10 14:20:23 2014 +0200
@@ -0,0 +1,225 @@
+(function(){science = {version: "1.7.0"}; // semver
+science.ascending = function(a, b) {
+  return a - b;
+};
+// Euler's constant.
+science.EULER = .5772156649015329;
+// Compute exp(x) - 1 accurately for small x.
+science.expm1 = function(x) {
+  return (x < 1e-5 && x > -1e-5) ? x + .5 * x * x : Math.exp(x) - 1;
+};
+science.functor = function(v) {
+  return typeof v === "function" ? v : function() { return v; };
+};
+// Based on:
+// http://www.johndcook.com/blog/2010/06/02/whats-so-hard-about-finding-a-hypotenuse/
+science.hypot = function(x, y) {
+  x = Math.abs(x);
+  y = Math.abs(y);
+  var max,
+      min;
+  if (x > y) { max = x; min = y; }
+  else       { max = y; min = x; }
+  var r = min / max;
+  return max * Math.sqrt(1 + r * r);
+};
+science.quadratic = function() {
+  var complex = false;
+
+  function quadratic(a, b, c) {
+    var d = b * b - 4 * a * c;
+    if (d > 0) {
+      d = Math.sqrt(d) / (2 * a);
+      return complex
+        ? [{r: -b - d, i: 0}, {r: -b + d, i: 0}]
+        : [-b - d, -b + d];
+    } else if (d === 0) {
+      d = -b / (2 * a);
+      return complex ? [{r: d, i: 0}] : [d];
+    } else {
+      if (complex) {
+        d = Math.sqrt(-d) / (2 * a);
+        return [
+          {r: -b, i: -d},
+          {r: -b, i: d}
+        ];
+      }
+      return [];
+    }
+  }
+
+  quadratic.complex = function(x) {
+    if (!arguments.length) return complex;
+    complex = x;
+    return quadratic;
+  };
+
+  return quadratic;
+};
+// Constructs a multi-dimensional array filled with zeroes.
+science.zeroes = function(n) {
+  var i = -1,
+      a = [];
+  if (arguments.length === 1)
+    while (++i < n)
+      a[i] = 0;
+  else
+    while (++i < n)
+      a[i] = science.zeroes.apply(
+        this, Array.prototype.slice.call(arguments, 1));
+  return a;
+};
+science.vector = {};
+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