Skip to content

Instantly share code, notes, and snippets.

@jrideout
Last active December 24, 2015 16:19
Show Gist options
  • Save jrideout/6826603 to your computer and use it in GitHub Desktop.
Save jrideout/6826603 to your computer and use it in GitHub Desktop.
DC Iris Demo

DC Iris Demo

A demo of dc.js exploring the standard Iris data set and using PCA from node-sylvester and pretty histogram binning from histogram-pretty.

<!DOCTYPE HTML>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="http://nickqizhu.github.io/dc.js/css/dc.css"/>
<body>
<script src="http://nickqizhu.github.io/dc.js/js/crossfilter.js"></script>
<script src="http://nickqizhu.github.io/dc.js/js/d3.js"></script>
<script src="http://nickqizhu.github.io/dc.js/js/dc.js"></script>
<script src="http://rawgithub.com/jrideout/histogram-pretty/master/histogram-pretty.js"></script>
<script src="sylvester.js"></script>
<script>
// browserify -r sylvester > sylvester.js
var Matrix = require('sylvester').Matrix;
d3.csv('iris.csv',
function(d,i) {
return {
sample: i,
sepalLength: +d.sepalLength,
sepalWidth: +d.sepalWidth,
petalLength: +d.petalLength,
petalWidth: +d.petalWidth,
class: d.class.split('-')[1]
};
},function(err,iris){
var irisToArray = function(d) {
return [d.sepalLength,d.sepalWidth,d.petalLength,d.petalWidth];
};
var irisMatrix = Matrix.create(iris.map(irisToArray));
irisMatrix.pcaProject(2).Z.elements.forEach(function(d,i) {
iris[i].pca1 = d[0];
iris[i].pca2 = d[1];
});
var ndx = crossfilter(iris),
dims = {},
groups = {};
['sepalLength','sepalWidth','petalLength','petalWidth'].forEach(function(n) {
var vector = iris.map(dc.pluck(n)),
hist = histogram(vector),
ticks = d3.range.apply(d3,hist.tickRange(8));
dims[n] = ndx.dimension(dc.pluck(n,hist.fun));
groups[n] = dims[n].group();
d3.select("body").append("div").attr("id", n);
dc.barChart("#" + n)
.dimension(dims[n]).group(groups[n])
.width(300).height(300)
.elasticY(true)
.yAxisLabel(n)
.elasticX(true)
.x(d3.scale.linear())
.xUnits(dc.units.fp.precision(hist.size))
.xAxis().tickValues(ticks);
});
dims.sample = ndx.dimension(dc.pluck('sample'));
groups.sample = dims.sample.group().reduce(
function(p,v) {return v;},
function(p,v) {return {};},function(){});
d3.select("body").append("div").attr("id", 'pca');
dc.bubbleChart("#pca")
.height(300)
.width(600)
.dimension(dims.sample).group(groups.sample)
.keyAccessor(function (p) {
return p.value.pca2;
})
.valueAccessor(function (p) {
return p.value.pca1;
})
.radiusValueAccessor(function (p) {
return 0.1;
})
.x(d3.scale.linear().domain(d3.extent(iris.map(dc.pluck('pca2')))))
.ordinalColors(['#1f77b4','#ff7f0e','#2ca02c'])
.colorDomain(['setosa','versicolor','virginica'])
.colorAccessor(function (d) {
return d.value.class;
})
.data(function() {
return groups.sample.all().filter(function(d){return d.value.pca1 !== undefined;});
});
dc.renderAll();
});
</script>
</body>
sepalLength sepalWidth petalLength petalWidth class
5.1 3.5 1.4 0.2 Iris-setosa
4.9 3.0 1.4 0.2 Iris-setosa
4.7 3.2 1.3 0.2 Iris-setosa
4.6 3.1 1.5 0.2 Iris-setosa
5.0 3.6 1.4 0.2 Iris-setosa
5.4 3.9 1.7 0.4 Iris-setosa
4.6 3.4 1.4 0.3 Iris-setosa
5.0 3.4 1.5 0.2 Iris-setosa
4.4 2.9 1.4 0.2 Iris-setosa
4.9 3.1 1.5 0.1 Iris-setosa
5.4 3.7 1.5 0.2 Iris-setosa
4.8 3.4 1.6 0.2 Iris-setosa
4.8 3.0 1.4 0.1 Iris-setosa
4.3 3.0 1.1 0.1 Iris-setosa
5.8 4.0 1.2 0.2 Iris-setosa
5.7 4.4 1.5 0.4 Iris-setosa
5.4 3.9 1.3 0.4 Iris-setosa
5.1 3.5 1.4 0.3 Iris-setosa
5.7 3.8 1.7 0.3 Iris-setosa
5.1 3.8 1.5 0.3 Iris-setosa
5.4 3.4 1.7 0.2 Iris-setosa
5.1 3.7 1.5 0.4 Iris-setosa
4.6 3.6 1.0 0.2 Iris-setosa
5.1 3.3 1.7 0.5 Iris-setosa
4.8 3.4 1.9 0.2 Iris-setosa
5.0 3.0 1.6 0.2 Iris-setosa
5.0 3.4 1.6 0.4 Iris-setosa
5.2 3.5 1.5 0.2 Iris-setosa
5.2 3.4 1.4 0.2 Iris-setosa
4.7 3.2 1.6 0.2 Iris-setosa
4.8 3.1 1.6 0.2 Iris-setosa
5.4 3.4 1.5 0.4 Iris-setosa
5.2 4.1 1.5 0.1 Iris-setosa
5.5 4.2 1.4 0.2 Iris-setosa
4.9 3.1 1.5 0.1 Iris-setosa
5.0 3.2 1.2 0.2 Iris-setosa
5.5 3.5 1.3 0.2 Iris-setosa
4.9 3.1 1.5 0.1 Iris-setosa
4.4 3.0 1.3 0.2 Iris-setosa
5.1 3.4 1.5 0.2 Iris-setosa
5.0 3.5 1.3 0.3 Iris-setosa
4.5 2.3 1.3 0.3 Iris-setosa
4.4 3.2 1.3 0.2 Iris-setosa
5.0 3.5 1.6 0.6 Iris-setosa
5.1 3.8 1.9 0.4 Iris-setosa
4.8 3.0 1.4 0.3 Iris-setosa
5.1 3.8 1.6 0.2 Iris-setosa
4.6 3.2 1.4 0.2 Iris-setosa
5.3 3.7 1.5 0.2 Iris-setosa
5.0 3.3 1.4 0.2 Iris-setosa
7.0 3.2 4.7 1.4 Iris-versicolor
6.4 3.2 4.5 1.5 Iris-versicolor
6.9 3.1 4.9 1.5 Iris-versicolor
5.5 2.3 4.0 1.3 Iris-versicolor
6.5 2.8 4.6 1.5 Iris-versicolor
5.7 2.8 4.5 1.3 Iris-versicolor
6.3 3.3 4.7 1.6 Iris-versicolor
4.9 2.4 3.3 1.0 Iris-versicolor
6.6 2.9 4.6 1.3 Iris-versicolor
5.2 2.7 3.9 1.4 Iris-versicolor
5.0 2.0 3.5 1.0 Iris-versicolor
5.9 3.0 4.2 1.5 Iris-versicolor
6.0 2.2 4.0 1.0 Iris-versicolor
6.1 2.9 4.7 1.4 Iris-versicolor
5.6 2.9 3.6 1.3 Iris-versicolor
6.7 3.1 4.4 1.4 Iris-versicolor
5.6 3.0 4.5 1.5 Iris-versicolor
5.8 2.7 4.1 1.0 Iris-versicolor
6.2 2.2 4.5 1.5 Iris-versicolor
5.6 2.5 3.9 1.1 Iris-versicolor
5.9 3.2 4.8 1.8 Iris-versicolor
6.1 2.8 4.0 1.3 Iris-versicolor
6.3 2.5 4.9 1.5 Iris-versicolor
6.1 2.8 4.7 1.2 Iris-versicolor
6.4 2.9 4.3 1.3 Iris-versicolor
6.6 3.0 4.4 1.4 Iris-versicolor
6.8 2.8 4.8 1.4 Iris-versicolor
6.7 3.0 5.0 1.7 Iris-versicolor
6.0 2.9 4.5 1.5 Iris-versicolor
5.7 2.6 3.5 1.0 Iris-versicolor
5.5 2.4 3.8 1.1 Iris-versicolor
5.5 2.4 3.7 1.0 Iris-versicolor
5.8 2.7 3.9 1.2 Iris-versicolor
6.0 2.7 5.1 1.6 Iris-versicolor
5.4 3.0 4.5 1.5 Iris-versicolor
6.0 3.4 4.5 1.6 Iris-versicolor
6.7 3.1 4.7 1.5 Iris-versicolor
6.3 2.3 4.4 1.3 Iris-versicolor
5.6 3.0 4.1 1.3 Iris-versicolor
5.5 2.5 4.0 1.3 Iris-versicolor
5.5 2.6 4.4 1.2 Iris-versicolor
6.1 3.0 4.6 1.4 Iris-versicolor
5.8 2.6 4.0 1.2 Iris-versicolor
5.0 2.3 3.3 1.0 Iris-versicolor
5.6 2.7 4.2 1.3 Iris-versicolor
5.7 3.0 4.2 1.2 Iris-versicolor
5.7 2.9 4.2 1.3 Iris-versicolor
6.2 2.9 4.3 1.3 Iris-versicolor
5.1 2.5 3.0 1.1 Iris-versicolor
5.7 2.8 4.1 1.3 Iris-versicolor
6.3 3.3 6.0 2.5 Iris-virginica
5.8 2.7 5.1 1.9 Iris-virginica
7.1 3.0 5.9 2.1 Iris-virginica
6.3 2.9 5.6 1.8 Iris-virginica
6.5 3.0 5.8 2.2 Iris-virginica
7.6 3.0 6.6 2.1 Iris-virginica
4.9 2.5 4.5 1.7 Iris-virginica
7.3 2.9 6.3 1.8 Iris-virginica
6.7 2.5 5.8 1.8 Iris-virginica
7.2 3.6 6.1 2.5 Iris-virginica
6.5 3.2 5.1 2.0 Iris-virginica
6.4 2.7 5.3 1.9 Iris-virginica
6.8 3.0 5.5 2.1 Iris-virginica
5.7 2.5 5.0 2.0 Iris-virginica
5.8 2.8 5.1 2.4 Iris-virginica
6.4 3.2 5.3 2.3 Iris-virginica
6.5 3.0 5.5 1.8 Iris-virginica
7.7 3.8 6.7 2.2 Iris-virginica
7.7 2.6 6.9 2.3 Iris-virginica
6.0 2.2 5.0 1.5 Iris-virginica
6.9 3.2 5.7 2.3 Iris-virginica
5.6 2.8 4.9 2.0 Iris-virginica
7.7 2.8 6.7 2.0 Iris-virginica
6.3 2.7 4.9 1.8 Iris-virginica
6.7 3.3 5.7 2.1 Iris-virginica
7.2 3.2 6.0 1.8 Iris-virginica
6.2 2.8 4.8 1.8 Iris-virginica
6.1 3.0 4.9 1.8 Iris-virginica
6.4 2.8 5.6 2.1 Iris-virginica
7.2 3.0 5.8 1.6 Iris-virginica
7.4 2.8 6.1 1.9 Iris-virginica
7.9 3.8 6.4 2.0 Iris-virginica
6.4 2.8 5.6 2.2 Iris-virginica
6.3 2.8 5.1 1.5 Iris-virginica
6.1 2.6 5.6 1.4 Iris-virginica
7.7 3.0 6.1 2.3 Iris-virginica
6.3 3.4 5.6 2.4 Iris-virginica
6.4 3.1 5.5 1.8 Iris-virginica
6.0 3.0 4.8 1.8 Iris-virginica
6.9 3.1 5.4 2.1 Iris-virginica
6.7 3.1 5.6 2.4 Iris-virginica
6.9 3.1 5.1 2.3 Iris-virginica
5.8 2.7 5.1 1.9 Iris-virginica
6.8 3.2 5.9 2.3 Iris-virginica
6.7 3.3 5.7 2.5 Iris-virginica
6.7 3.0 5.2 2.3 Iris-virginica
6.3 2.5 5.0 1.9 Iris-virginica
6.5 3.0 5.2 2.0 Iris-virginica
6.2 3.4 5.4 2.3 Iris-virginica
5.9 3.0 5.1 1.8 Iris-virginica
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
//
// The shims in this file are not fully implemented shims for the ES5
// features, but do work for the particular usecases there is in
// the other modules.
//
var toString = Object.prototype.toString;
var hasOwnProperty = Object.prototype.hasOwnProperty;
// Array.isArray is supported in IE9
function isArray(xs) {
return toString.call(xs) === '[object Array]';
}
exports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;
// Array.prototype.indexOf is supported in IE9
exports.indexOf = function indexOf(xs, x) {
if (xs.indexOf) return xs.indexOf(x);
for (var i = 0; i < xs.length; i++) {
if (x === xs[i]) return i;
}
return -1;
};
// Array.prototype.filter is supported in IE9
exports.filter = function filter(xs, fn) {
if (xs.filter) return xs.filter(fn);
var res = [];
for (var i = 0; i < xs.length; i++) {
if (fn(xs[i], i, xs)) res.push(xs[i]);
}
return res;
};
// Array.prototype.forEach is supported in IE9
exports.forEach = function forEach(xs, fn, self) {
if (xs.forEach) return xs.forEach(fn, self);
for (var i = 0; i < xs.length; i++) {
fn.call(self, xs[i], i, xs);
}
};
// Array.prototype.map is supported in IE9
exports.map = function map(xs, fn) {
if (xs.map) return xs.map(fn);
var out = new Array(xs.length);
for (var i = 0; i < xs.length; i++) {
out[i] = fn(xs[i], i, xs);
}
return out;
};
// Array.prototype.reduce is supported in IE9
exports.reduce = function reduce(array, callback, opt_initialValue) {
if (array.reduce) return array.reduce(callback, opt_initialValue);
var value, isValueSet = false;
if (2 < arguments.length) {
value = opt_initialValue;
isValueSet = true;
}
for (var i = 0, l = array.length; l > i; ++i) {
if (array.hasOwnProperty(i)) {
if (isValueSet) {
value = callback(value, array[i], i, array);
}
else {
value = array[i];
isValueSet = true;
}
}
}
return value;
};
// String.prototype.substr - negative index don't work in IE8
if ('ab'.substr(-1) !== 'b') {
exports.substr = function (str, start, length) {
// did we get a negative start, calculate how much it is from the beginning of the string
if (start < 0) start = str.length + start;
// call the original function
return str.substr(start, length);
};
} else {
exports.substr = function (str, start, length) {
return str.substr(start, length);
};
}
// String.prototype.trim is supported in IE9
exports.trim = function (str) {
if (str.trim) return str.trim();
return str.replace(/^\s+|\s+$/g, '');
};
// Function.prototype.bind is supported in IE9
exports.bind = function () {
var args = Array.prototype.slice.call(arguments);
var fn = args.shift();
if (fn.bind) return fn.bind.apply(fn, args);
var self = args.shift();
return function () {
fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));
};
};
// Object.create is supported in IE9
function create(prototype, properties) {
var object;
if (prototype === null) {
object = { '__proto__' : null };
}
else {
if (typeof prototype !== 'object') {
throw new TypeError(
'typeof prototype[' + (typeof prototype) + '] != \'object\''
);
}
var Type = function () {};
Type.prototype = prototype;
object = new Type();
object.__proto__ = prototype;
}
if (typeof properties !== 'undefined' && Object.defineProperties) {
Object.defineProperties(object, properties);
}
return object;
}
exports.create = typeof Object.create === 'function' ? Object.create : create;
// Object.keys and Object.getOwnPropertyNames is supported in IE9 however
// they do show a description and number property on Error objects
function notObject(object) {
return ((typeof object != "object" && typeof object != "function") || object === null);
}
function keysShim(object) {
if (notObject(object)) {
throw new TypeError("Object.keys called on a non-object");
}
var result = [];
for (var name in object) {
if (hasOwnProperty.call(object, name)) {
result.push(name);
}
}
return result;
}
// getOwnPropertyNames is almost the same as Object.keys one key feature
// is that it returns hidden properties, since that can't be implemented,
// this feature gets reduced so it just shows the length property on arrays
function propertyShim(object) {
if (notObject(object)) {
throw new TypeError("Object.getOwnPropertyNames called on a non-object");
}
var result = keysShim(object);
if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {
result.push('length');
}
return result;
}
var keys = typeof Object.keys === 'function' ? Object.keys : keysShim;
var getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?
Object.getOwnPropertyNames : propertyShim;
if (new Error().hasOwnProperty('description')) {
var ERROR_PROPERTY_FILTER = function (obj, array) {
if (toString.call(obj) === '[object Error]') {
array = exports.filter(array, function (name) {
return name !== 'description' && name !== 'number' && name !== 'message';
});
}
return array;
};
exports.keys = function (object) {
return ERROR_PROPERTY_FILTER(object, keys(object));
};
exports.getOwnPropertyNames = function (object) {
return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));
};
} else {
exports.keys = keys;
exports.getOwnPropertyNames = getOwnPropertyNames;
}
// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements
function valueObject(value, key) {
return { value: value[key] };
}
if (typeof Object.getOwnPropertyDescriptor === 'function') {
try {
Object.getOwnPropertyDescriptor({'a': 1}, 'a');
exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
} catch (e) {
// IE8 dom element issue - use a try catch and default to valueObject
exports.getOwnPropertyDescriptor = function (value, key) {
try {
return Object.getOwnPropertyDescriptor(value, key);
} catch (e) {
return valueObject(value, key);
}
};
}
} else {
exports.getOwnPropertyDescriptor = valueObject;
}
},{}],2:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var util = require('util');
function EventEmitter() {
this._events = this._events || {};
this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;
// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
EventEmitter.defaultMaxListeners = 10;
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function(n) {
if (!util.isNumber(n) || n < 0)
throw TypeError('n must be a positive number');
this._maxListeners = n;
return this;
};
EventEmitter.prototype.emit = function(type) {
var er, handler, len, args, i, listeners;
if (!this._events)
this._events = {};
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events.error ||
(util.isObject(this._events.error) && !this._events.error.length)) {
er = arguments[1];
if (er instanceof Error) {
throw er; // Unhandled 'error' event
} else {
throw TypeError('Uncaught, unspecified "error" event.');
}
return false;
}
}
handler = this._events[type];
if (util.isUndefined(handler))
return false;
if (util.isFunction(handler)) {
switch (arguments.length) {
// fast cases
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
// slower
default:
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
handler.apply(this, args);
}
} else if (util.isObject(handler)) {
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
listeners = handler.slice();
len = listeners.length;
for (i = 0; i < len; i++)
listeners[i].apply(this, args);
}
return true;
};
EventEmitter.prototype.addListener = function(type, listener) {
var m;
if (!util.isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events)
this._events = {};
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (this._events.newListener)
this.emit('newListener', type,
util.isFunction(listener.listener) ?
listener.listener : listener);
if (!this._events[type])
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
else if (util.isObject(this._events[type]))
// If we've already got an array, just append.
this._events[type].push(listener);
else
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
// Check for listener leak
if (util.isObject(this._events[type]) && !this._events[type].warned) {
var m;
if (!util.isUndefined(this._maxListeners)) {
m = this._maxListeners;
} else {
m = EventEmitter.defaultMaxListeners;
}
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this._events[type].length);
console.trace();
}
}
return this;
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.once = function(type, listener) {
if (!util.isFunction(listener))
throw TypeError('listener must be a function');
function g() {
this.removeListener(type, g);
listener.apply(this, arguments);
}
g.listener = listener;
this.on(type, g);
return this;
};
// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
var list, position, length, i;
if (!util.isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events || !this._events[type])
return this;
list = this._events[type];
length = list.length;
position = -1;
if (list === listener ||
(util.isFunction(list.listener) && list.listener === listener)) {
delete this._events[type];
if (this._events.removeListener)
this.emit('removeListener', type, listener);
} else if (util.isObject(list)) {
for (i = length; i-- > 0;) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
position = i;
break;
}
}
if (position < 0)
return this;
if (list.length === 1) {
list.length = 0;
delete this._events[type];
} else {
list.splice(position, 1);
}
if (this._events.removeListener)
this.emit('removeListener', type, listener);
}
return this;
};
EventEmitter.prototype.removeAllListeners = function(type) {
var key, listeners;
if (!this._events)
return this;
// not listening for removeListener, no need to emit
if (!this._events.removeListener) {
if (arguments.length === 0)
this._events = {};
else if (this._events[type])
delete this._events[type];
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
for (key in this._events) {
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = {};
return this;
}
listeners = this._events[type];
if (util.isFunction(listeners)) {
this.removeListener(type, listeners);
} else {
// LIFO order
while (listeners.length)
this.removeListener(type, listeners[listeners.length - 1]);
}
delete this._events[type];
return this;
};
EventEmitter.prototype.listeners = function(type) {
var ret;
if (!this._events || !this._events[type])
ret = [];
else if (util.isFunction(this._events[type]))
ret = [this._events[type]];
else
ret = this._events[type].slice();
return ret;
};
EventEmitter.listenerCount = function(emitter, type) {
var ret;
if (!emitter._events || !emitter._events[type])
ret = 0;
else if (util.isFunction(emitter._events[type]))
ret = 1;
else
ret = emitter._events[type].length;
return ret;
};
},{"util":5}],3:[function(require,module,exports){
// not implemented
// The reason for having an empty file and not throwing is to allow
// untraditional implementation of this module.
},{}],4:[function(require,module,exports){
var process=require("__browserify_process");// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var util = require('util');
var shims = require('_shims');
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i];
if (last === '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Split a filename into [root, dir, basename, ext], unix version
// 'root' is just a slash, or nothing.
var splitPathRe =
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
var splitPath = function(filename) {
return splitPathRe.exec(filename).slice(1);
};
// path.resolve([from ...], to)
// posix version
exports.resolve = function() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path = (i >= 0) ? arguments[i] : process.cwd();
// Skip empty and invalid entries
if (!util.isString(path)) {
throw new TypeError('Arguments to path.resolve must be strings');
} else if (!path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function(path) {
var isAbsolute = exports.isAbsolute(path),
trailingSlash = shims.substr(path, -1) === '/';
// Normalize the path
path = normalizeArray(shims.filter(path.split('/'), function(p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.isAbsolute = function(path) {
return path.charAt(0) === '/';
};
// posix version
exports.join = function() {
var paths = Array.prototype.slice.call(arguments, 0);
return exports.normalize(shims.filter(paths, function(p, index) {
if (!util.isString(p)) {
throw new TypeError('Arguments to path.join must be strings');
}
return p;
}).join('/'));
};
// path.relative(from, to)
// posix version
exports.relative = function(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
exports.sep = '/';
exports.delimiter = ':';
exports.dirname = function(path) {
var result = splitPath(path),
root = result[0],
dir = result[1];
if (!root && !dir) {
// No dirname whatsoever
return '.';
}
if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
}
return root + dir;
};
exports.basename = function(path, ext) {
var f = splitPath(path)[2];
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
};
exports.extname = function(path) {
return splitPath(path)[3];
};
},{"__browserify_process":7,"_shims":1,"util":5}],5:[function(require,module,exports){
var Buffer=require("__browserify_Buffer").Buffer;// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var shims = require('_shims');
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
shims.forEach(array, function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = shims.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = shims.getOwnPropertyNames(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
shims.forEach(keys, function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (shims.indexOf(ctx.seen, desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = shims.reduce(output, function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return shims.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) && objectToString(e) === '[object Error]';
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
function isBuffer(arg) {
return arg instanceof Buffer;
}
exports.isBuffer = isBuffer;
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = function(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = shims.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = shims.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
},{"__browserify_Buffer":6,"_shims":1}],6:[function(require,module,exports){
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
var e, m,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = isBE ? 0 : (nBytes - 1),
d = isBE ? 1 : -1,
s = buffer[offset + i];
i += d;
e = s & ((1 << (-nBits)) - 1);
s >>= (-nBits);
nBits += eLen;
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
m = e & ((1 << (-nBits)) - 1);
e >>= (-nBits);
nBits += mLen;
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
if (e === 0) {
e = 1 - eBias;
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity);
} else {
m = m + Math.pow(2, mLen);
e = e - eBias;
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
var e, m, c,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
i = isBE ? (nBytes - 1) : 0,
d = isBE ? -1 : 1,
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
value = Math.abs(value);
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0;
e = eMax;
} else {
e = Math.floor(Math.log(value) / Math.LN2);
if (value * (c = Math.pow(2, -e)) < 1) {
e--;
c *= 2;
}
if (e + eBias >= 1) {
value += rt / c;
} else {
value += rt * Math.pow(2, 1 - eBias);
}
if (value * c >= 2) {
e++;
c /= 2;
}
if (e + eBias >= eMax) {
m = 0;
e = eMax;
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen);
e = e + eBias;
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
e = 0;
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
e = (e << mLen) | m;
eLen += mLen;
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
buffer[offset + i - d] |= s * 128;
};
},{}],"q9TxCC":[function(require,module,exports){
var assert;
exports.Buffer = Buffer;
exports.SlowBuffer = Buffer;
Buffer.poolSize = 8192;
exports.INSPECT_MAX_BYTES = 50;
function stringtrim(str) {
if (str.trim) return str.trim();
return str.replace(/^\s+|\s+$/g, '');
}
function Buffer(subject, encoding, offset) {
if(!assert) assert= require('assert');
if (!(this instanceof Buffer)) {
return new Buffer(subject, encoding, offset);
}
this.parent = this;
this.offset = 0;
// Work-around: node's base64 implementation
// allows for non-padded strings while base64-js
// does not..
if (encoding == "base64" && typeof subject == "string") {
subject = stringtrim(subject);
while (subject.length % 4 != 0) {
subject = subject + "=";
}
}
var type;
// Are we slicing?
if (typeof offset === 'number') {
this.length = coerce(encoding);
// slicing works, with limitations (no parent tracking/update)
// check https://github.com/toots/buffer-browserify/issues/19
for (var i = 0; i < this.length; i++) {
this[i] = subject.get(i+offset);
}
} else {
// Find the length
switch (type = typeof subject) {
case 'number':
this.length = coerce(subject);
break;
case 'string':
this.length = Buffer.byteLength(subject, encoding);
break;
case 'object': // Assume object is an array
this.length = coerce(subject.length);
break;
default:
throw new Error('First argument needs to be a number, ' +
'array or string.');
}
// Treat array-ish objects as a byte array.
if (isArrayIsh(subject)) {
for (var i = 0; i < this.length; i++) {
if (subject instanceof Buffer) {
this[i] = subject.readUInt8(i);
}
else {
this[i] = subject[i];
}
}
} else if (type == 'string') {
// We are a string
this.length = this.write(subject, 0, encoding);
} else if (type === 'number') {
for (var i = 0; i < this.length; i++) {
this[i] = 0;
}
}
}
}
Buffer.prototype.get = function get(i) {
if (i < 0 || i >= this.length) throw new Error('oob');
return this[i];
};
Buffer.prototype.set = function set(i, v) {
if (i < 0 || i >= this.length) throw new Error('oob');
return this[i] = v;
};
Buffer.byteLength = function (str, encoding) {
switch (encoding || "utf8") {
case 'hex':
return str.length / 2;
case 'utf8':
case 'utf-8':
return utf8ToBytes(str).length;
case 'ascii':
case 'binary':
return str.length;
case 'base64':
return base64ToBytes(str).length;
default:
throw new Error('Unknown encoding');
}
};
Buffer.prototype.utf8Write = function (string, offset, length) {
var bytes, pos;
return Buffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
};
Buffer.prototype.asciiWrite = function (string, offset, length) {
var bytes, pos;
return Buffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
};
Buffer.prototype.binaryWrite = Buffer.prototype.asciiWrite;
Buffer.prototype.base64Write = function (string, offset, length) {
var bytes, pos;
return Buffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
};
Buffer.prototype.base64Slice = function (start, end) {
var bytes = Array.prototype.slice.apply(this, arguments)
return require("base64-js").fromByteArray(bytes);
};
Buffer.prototype.utf8Slice = function () {
var bytes = Array.prototype.slice.apply(this, arguments);
var res = "";
var tmp = "";
var i = 0;
while (i < bytes.length) {
if (bytes[i] <= 0x7F) {
res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
tmp = "";
} else
tmp += "%" + bytes[i].toString(16);
i++;
}
return res + decodeUtf8Char(tmp);
}
Buffer.prototype.asciiSlice = function () {
var bytes = Array.prototype.slice.apply(this, arguments);
var ret = "";
for (var i = 0; i < bytes.length; i++)
ret += String.fromCharCode(bytes[i]);
return ret;
}
Buffer.prototype.binarySlice = Buffer.prototype.asciiSlice;
Buffer.prototype.inspect = function() {
var out = [],
len = this.length;
for (var i = 0; i < len; i++) {
out[i] = toHex(this[i]);
if (i == exports.INSPECT_MAX_BYTES) {
out[i + 1] = '...';
break;
}
}
return '<Buffer ' + out.join(' ') + '>';
};
Buffer.prototype.hexSlice = function(start, end) {
var len = this.length;
if (!start || start < 0) start = 0;
if (!end || end < 0 || end > len) end = len;
var out = '';
for (var i = start; i < end; i++) {
out += toHex(this[i]);
}
return out;
};
Buffer.prototype.toString = function(encoding, start, end) {
encoding = String(encoding || 'utf8').toLowerCase();
start = +start || 0;
if (typeof end == 'undefined') end = this.length;
// Fastpath empty strings
if (+end == start) {
return '';
}
switch (encoding) {
case 'hex':
return this.hexSlice(start, end);
case 'utf8':
case 'utf-8':
return this.utf8Slice(start, end);
case 'ascii':
return this.asciiSlice(start, end);
case 'binary':
return this.binarySlice(start, end);
case 'base64':
return this.base64Slice(start, end);
case 'ucs2':
case 'ucs-2':
return this.ucs2Slice(start, end);
default:
throw new Error('Unknown encoding');
}
};
Buffer.prototype.hexWrite = function(string, offset, length) {
offset = +offset || 0;
var remaining = this.length - offset;
if (!length) {
length = remaining;
} else {
length = +length;
if (length > remaining) {
length = remaining;
}
}
// must be an even number of digits
var strLen = string.length;
if (strLen % 2) {
throw new Error('Invalid hex string');
}
if (length > strLen / 2) {
length = strLen / 2;
}
for (var i = 0; i < length; i++) {
var byte = parseInt(string.substr(i * 2, 2), 16);
if (isNaN(byte)) throw new Error('Invalid hex string');
this[offset + i] = byte;
}
Buffer._charsWritten = i * 2;
return i;
};
Buffer.prototype.write = function(string, offset, length, encoding) {
// Support both (string, offset, length, encoding)
// and the legacy (string, encoding, offset, length)
if (isFinite(offset)) {
if (!isFinite(length)) {
encoding = length;
length = undefined;
}
} else { // legacy
var swap = encoding;
encoding = offset;
offset = length;
length = swap;
}
offset = +offset || 0;
var remaining = this.length - offset;
if (!length) {
length = remaining;
} else {
length = +length;
if (length > remaining) {
length = remaining;
}
}
encoding = String(encoding || 'utf8').toLowerCase();
switch (encoding) {
case 'hex':
return this.hexWrite(string, offset, length);
case 'utf8':
case 'utf-8':
return this.utf8Write(string, offset, length);
case 'ascii':
return this.asciiWrite(string, offset, length);
case 'binary':
return this.binaryWrite(string, offset, length);
case 'base64':
return this.base64Write(string, offset, length);
case 'ucs2':
case 'ucs-2':
return this.ucs2Write(string, offset, length);
default:
throw new Error('Unknown encoding');
}
};
// slice(start, end)
function clamp(index, len, defaultValue) {
if (typeof index !== 'number') return defaultValue;
index = ~~index; // Coerce to integer.
if (index >= len) return len;
if (index >= 0) return index;
index += len;
if (index >= 0) return index;
return 0;
}
Buffer.prototype.slice = function(start, end) {
var len = this.length;
start = clamp(start, len, 0);
end = clamp(end, len, len);
return new Buffer(this, end - start, +start);
};
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function(target, target_start, start, end) {
var source = this;
start || (start = 0);
if (end === undefined || isNaN(end)) {
end = this.length;
}
target_start || (target_start = 0);
if (end < start) throw new Error('sourceEnd < sourceStart');
// Copy 0 bytes; we're done
if (end === start) return 0;
if (target.length == 0 || source.length == 0) return 0;
if (target_start < 0 || target_start >= target.length) {
throw new Error('targetStart out of bounds');
}
if (start < 0 || start >= source.length) {
throw new Error('sourceStart out of bounds');
}
if (end < 0 || end > source.length) {
throw new Error('sourceEnd out of bounds');
}
// Are we oob?
if (end > this.length) {
end = this.length;
}
if (target.length - target_start < end - start) {
end = target.length - target_start + start;
}
var temp = [];
for (var i=start; i<end; i++) {
assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
temp.push(this[i]);
}
for (var i=target_start; i<target_start+temp.length; i++) {
target[i] = temp[i-target_start];
}
};
// fill(value, start=0, end=buffer.length)
Buffer.prototype.fill = function fill(value, start, end) {
value || (value = 0);
start || (start = 0);
end || (end = this.length);
if (typeof value === 'string') {
value = value.charCodeAt(0);
}
if (!(typeof value === 'number') || isNaN(value)) {
throw new Error('value is not a number');
}
if (end < start) throw new Error('end < start');
// Fill 0 bytes; we're done
if (end === start) return 0;
if (this.length == 0) return 0;
if (start < 0 || start >= this.length) {
throw new Error('start out of bounds');
}
if (end < 0 || end > this.length) {
throw new Error('end out of bounds');
}
for (var i = start; i < end; i++) {
this[i] = value;
}
}
// Static methods
Buffer.isBuffer = function isBuffer(b) {
return b instanceof Buffer || b instanceof Buffer;
};
Buffer.concat = function (list, totalLength) {
if (!isArray(list)) {
throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
list should be an Array.");
}
if (list.length === 0) {
return new Buffer(0);
} else if (list.length === 1) {
return list[0];
}
if (typeof totalLength !== 'number') {
totalLength = 0;
for (var i = 0; i < list.length; i++) {
var buf = list[i];
totalLength += buf.length;
}
}
var buffer = new Buffer(totalLength);
var pos = 0;
for (var i = 0; i < list.length; i++) {
var buf = list[i];
buf.copy(buffer, pos);
pos += buf.length;
}
return buffer;
};
Buffer.isEncoding = function(encoding) {
switch ((encoding + '').toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'binary':
case 'base64':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
case 'raw':
return true;
default:
return false;
}
};
// helpers
function coerce(length) {
// Coerce length to a number (possibly NaN), round up
// in case it's fractional (e.g. 123.456) then do a
// double negate to coerce a NaN to 0. Easy, right?
length = ~~Math.ceil(+length);
return length < 0 ? 0 : length;
}
function isArray(subject) {
return (Array.isArray ||
function(subject){
return {}.toString.apply(subject) == '[object Array]'
})
(subject)
}
function isArrayIsh(subject) {
return isArray(subject) || Buffer.isBuffer(subject) ||
subject && typeof subject === 'object' &&
typeof subject.length === 'number';
}
function toHex(n) {
if (n < 16) return '0' + n.toString(16);
return n.toString(16);
}
function utf8ToBytes(str) {
var byteArray = [];
for (var i = 0; i < str.length; i++)
if (str.charCodeAt(i) <= 0x7F)
byteArray.push(str.charCodeAt(i));
else {
var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
for (var j = 0; j < h.length; j++)
byteArray.push(parseInt(h[j], 16));
}
return byteArray;
}
function asciiToBytes(str) {
var byteArray = []
for (var i = 0; i < str.length; i++ )
// Node's code seems to be doing this and not & 0x7F..
byteArray.push( str.charCodeAt(i) & 0xFF );
return byteArray;
}
function base64ToBytes(str) {
return require("base64-js").toByteArray(str);
}
function blitBuffer(src, dst, offset, length) {
var pos, i = 0;
while (i < length) {
if ((i+offset >= dst.length) || (i >= src.length))
break;
dst[i + offset] = src[i];
i++;
}
return i;
}
function decodeUtf8Char(str) {
try {
return decodeURIComponent(str);
} catch (err) {
return String.fromCharCode(0xFFFD); // UTF 8 invalid char
}
}
// read/write bit-twiddling
Buffer.prototype.readUInt8 = function(offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to read beyond buffer length');
}
if (offset >= buffer.length) return;
return buffer[offset];
};
function readUInt16(buffer, offset, isBigEndian, noAssert) {
var val = 0;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to read beyond buffer length');
}
if (offset >= buffer.length) return 0;
if (isBigEndian) {
val = buffer[offset] << 8;
if (offset + 1 < buffer.length) {
val |= buffer[offset + 1];
}
} else {
val = buffer[offset];
if (offset + 1 < buffer.length) {
val |= buffer[offset + 1] << 8;
}
}
return val;
}
Buffer.prototype.readUInt16LE = function(offset, noAssert) {
return readUInt16(this, offset, false, noAssert);
};
Buffer.prototype.readUInt16BE = function(offset, noAssert) {
return readUInt16(this, offset, true, noAssert);
};
function readUInt32(buffer, offset, isBigEndian, noAssert) {
var val = 0;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
if (offset >= buffer.length) return 0;
if (isBigEndian) {
if (offset + 1 < buffer.length)
val = buffer[offset + 1] << 16;
if (offset + 2 < buffer.length)
val |= buffer[offset + 2] << 8;
if (offset + 3 < buffer.length)
val |= buffer[offset + 3];
val = val + (buffer[offset] << 24 >>> 0);
} else {
if (offset + 2 < buffer.length)
val = buffer[offset + 2] << 16;
if (offset + 1 < buffer.length)
val |= buffer[offset + 1] << 8;
val |= buffer[offset];
if (offset + 3 < buffer.length)
val = val + (buffer[offset + 3] << 24 >>> 0);
}
return val;
}
Buffer.prototype.readUInt32LE = function(offset, noAssert) {
return readUInt32(this, offset, false, noAssert);
};
Buffer.prototype.readUInt32BE = function(offset, noAssert) {
return readUInt32(this, offset, true, noAssert);
};
/*
* Signed integer types, yay team! A reminder on how two's complement actually
* works. The first bit is the signed bit, i.e. tells us whether or not the
* number should be positive or negative. If the two's complement value is
* positive, then we're done, as it's equivalent to the unsigned representation.
*
* Now if the number is positive, you're pretty much done, you can just leverage
* the unsigned translations and return those. Unfortunately, negative numbers
* aren't quite that straightforward.
*
* At first glance, one might be inclined to use the traditional formula to
* translate binary numbers between the positive and negative values in two's
* complement. (Though it doesn't quite work for the most negative value)
* Mainly:
* - invert all the bits
* - add one to the result
*
* Of course, this doesn't quite work in Javascript. Take for example the value
* of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
* course, Javascript will do the following:
*
* > ~0xff80
* -65409
*
* Whoh there, Javascript, that's not quite right. But wait, according to
* Javascript that's perfectly correct. When Javascript ends up seeing the
* constant 0xff80, it has no notion that it is actually a signed number. It
* assumes that we've input the unsigned value 0xff80. Thus, when it does the
* binary negation, it casts it into a signed value, (positive 0xff80). Then
* when you perform binary negation on that, it turns it into a negative number.
*
* Instead, we're going to have to use the following general formula, that works
* in a rather Javascript friendly way. I'm glad we don't support this kind of
* weird numbering scheme in the kernel.
*
* (BIT-MAX - (unsigned)val + 1) * -1
*
* The astute observer, may think that this doesn't make sense for 8-bit numbers
* (really it isn't necessary for them). However, when you get 16-bit numbers,
* you do. Let's go back to our prior example and see how this will look:
*
* (0xffff - 0xff80 + 1) * -1
* (0x007f + 1) * -1
* (0x0080) * -1
*/
Buffer.prototype.readInt8 = function(offset, noAssert) {
var buffer = this;
var neg;
if (!noAssert) {
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to read beyond buffer length');
}
if (offset >= buffer.length) return;
neg = buffer[offset] & 0x80;
if (!neg) {
return (buffer[offset]);
}
return ((0xff - buffer[offset] + 1) * -1);
};
function readInt16(buffer, offset, isBigEndian, noAssert) {
var neg, val;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to read beyond buffer length');
}
val = readUInt16(buffer, offset, isBigEndian, noAssert);
neg = val & 0x8000;
if (!neg) {
return val;
}
return (0xffff - val + 1) * -1;
}
Buffer.prototype.readInt16LE = function(offset, noAssert) {
return readInt16(this, offset, false, noAssert);
};
Buffer.prototype.readInt16BE = function(offset, noAssert) {
return readInt16(this, offset, true, noAssert);
};
function readInt32(buffer, offset, isBigEndian, noAssert) {
var neg, val;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
val = readUInt32(buffer, offset, isBigEndian, noAssert);
neg = val & 0x80000000;
if (!neg) {
return (val);
}
return (0xffffffff - val + 1) * -1;
}
Buffer.prototype.readInt32LE = function(offset, noAssert) {
return readInt32(this, offset, false, noAssert);
};
Buffer.prototype.readInt32BE = function(offset, noAssert) {
return readInt32(this, offset, true, noAssert);
};
function readFloat(buffer, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
23, 4);
}
Buffer.prototype.readFloatLE = function(offset, noAssert) {
return readFloat(this, offset, false, noAssert);
};
Buffer.prototype.readFloatBE = function(offset, noAssert) {
return readFloat(this, offset, true, noAssert);
};
function readDouble(buffer, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset + 7 < buffer.length,
'Trying to read beyond buffer length');
}
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
52, 8);
}
Buffer.prototype.readDoubleLE = function(offset, noAssert) {
return readDouble(this, offset, false, noAssert);
};
Buffer.prototype.readDoubleBE = function(offset, noAssert) {
return readDouble(this, offset, true, noAssert);
};
/*
* We have to make sure that the value is a valid integer. This means that it is
* non-negative. It has no fractional component and that it does not exceed the
* maximum allowed value.
*
* value The number to check for validity
*
* max The maximum value
*/
function verifuint(value, max) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value >= 0,
'specified a negative value for writing an unsigned value');
assert.ok(value <= max, 'value is larger than maximum value for type');
assert.ok(Math.floor(value) === value, 'value has a fractional component');
}
Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xff);
}
if (offset < buffer.length) {
buffer[offset] = value;
}
};
function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xffff);
}
for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
buffer[offset + i] =
(value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
(isBigEndian ? 1 - i : i) * 8;
}
}
Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
writeUInt16(this, value, offset, false, noAssert);
};
Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
writeUInt16(this, value, offset, true, noAssert);
};
function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xffffffff);
}
for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
buffer[offset + i] =
(value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
}
}
Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
writeUInt32(this, value, offset, false, noAssert);
};
Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
writeUInt32(this, value, offset, true, noAssert);
};
/*
* We now move onto our friends in the signed number category. Unlike unsigned
* numbers, we're going to have to worry a bit more about how we put values into
* arrays. Since we are only worrying about signed 32-bit values, we're in
* slightly better shape. Unfortunately, we really can't do our favorite binary
* & in this system. It really seems to do the wrong thing. For example:
*
* > -32 & 0xff
* 224
*
* What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
* this aren't treated as a signed number. Ultimately a bad thing.
*
* What we're going to want to do is basically create the unsigned equivalent of
* our representation and pass that off to the wuint* functions. To do that
* we're going to do the following:
*
* - if the value is positive
* we can pass it directly off to the equivalent wuint
* - if the value is negative
* we do the following computation:
* mb + val + 1, where
* mb is the maximum unsigned value in that byte size
* val is the Javascript negative integer
*
*
* As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
* you do out the computations:
*
* 0xffff - 128 + 1
* 0xffff - 127
* 0xff80
*
* You can then encode this value as the signed version. This is really rather
* hacky, but it should work and get the job done which is our goal here.
*/
/*
* A series of checks to make sure we actually have a signed 32-bit number
*/
function verifsint(value, max, min) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value <= max, 'value larger than maximum allowed value');
assert.ok(value >= min, 'value smaller than minimum allowed value');
assert.ok(Math.floor(value) === value, 'value has a fractional component');
}
function verifIEEE754(value, max, min) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value <= max, 'value larger than maximum allowed value');
assert.ok(value >= min, 'value smaller than minimum allowed value');
}
Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7f, -0x80);
}
if (value >= 0) {
buffer.writeUInt8(value, offset, noAssert);
} else {
buffer.writeUInt8(0xff + value + 1, offset, noAssert);
}
};
function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7fff, -0x8000);
}
if (value >= 0) {
writeUInt16(buffer, value, offset, isBigEndian, noAssert);
} else {
writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
}
}
Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
writeInt16(this, value, offset, false, noAssert);
};
Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
writeInt16(this, value, offset, true, noAssert);
};
function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7fffffff, -0x80000000);
}
if (value >= 0) {
writeUInt32(buffer, value, offset, isBigEndian, noAssert);
} else {
writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
}
}
Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
writeInt32(this, value, offset, false, noAssert);
};
Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
writeInt32(this, value, offset, true, noAssert);
};
function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to write beyond buffer length');
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
}
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
23, 4);
}
Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
writeFloat(this, value, offset, false, noAssert);
};
Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
writeFloat(this, value, offset, true, noAssert);
};
function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 7 < buffer.length,
'Trying to write beyond buffer length');
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
}
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
52, 8);
}
Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
writeDouble(this, value, offset, false, noAssert);
};
Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
writeDouble(this, value, offset, true, noAssert);
};
},{"./buffer_ieee754":1,"assert":6,"base64-js":4}],"buffer-browserify":[function(require,module,exports){
module.exports=require('q9TxCC');
},{}],4:[function(require,module,exports){
(function (exports) {
'use strict';
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function b64ToByteArray(b64) {
var i, j, l, tmp, placeHolders, arr;
if (b64.length % 4 > 0) {
throw 'Invalid string. Length must be a multiple of 4';
}
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
placeHolders = b64.indexOf('=');
placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
// base64 is 4/3 + up to two characters of the original data
arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length;
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
arr.push((tmp & 0xFF0000) >> 16);
arr.push((tmp & 0xFF00) >> 8);
arr.push(tmp & 0xFF);
}
if (placeHolders === 2) {
tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
arr.push(tmp & 0xFF);
} else if (placeHolders === 1) {
tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
arr.push((tmp >> 8) & 0xFF);
arr.push(tmp & 0xFF);
}
return arr;
}
function uint8ToBase64(uint8) {
var i,
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
output = "",
temp, length;
function tripletToBase64 (num) {
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
};
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
output += tripletToBase64(temp);
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1];
output += lookup[temp >> 2];
output += lookup[(temp << 4) & 0x3F];
output += '==';
break;
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
output += lookup[temp >> 10];
output += lookup[(temp >> 4) & 0x3F];
output += lookup[(temp << 2) & 0x3F];
output += '=';
break;
}
return output;
}
module.exports.toByteArray = b64ToByteArray;
module.exports.fromByteArray = uint8ToBase64;
}());
},{}],5:[function(require,module,exports){
//
// The shims in this file are not fully implemented shims for the ES5
// features, but do work for the particular usecases there is in
// the other modules.
//
var toString = Object.prototype.toString;
var hasOwnProperty = Object.prototype.hasOwnProperty;
// Array.isArray is supported in IE9
function isArray(xs) {
return toString.call(xs) === '[object Array]';
}
exports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray;
// Array.prototype.indexOf is supported in IE9
exports.indexOf = function indexOf(xs, x) {
if (xs.indexOf) return xs.indexOf(x);
for (var i = 0; i < xs.length; i++) {
if (x === xs[i]) return i;
}
return -1;
};
// Array.prototype.filter is supported in IE9
exports.filter = function filter(xs, fn) {
if (xs.filter) return xs.filter(fn);
var res = [];
for (var i = 0; i < xs.length; i++) {
if (fn(xs[i], i, xs)) res.push(xs[i]);
}
return res;
};
// Array.prototype.forEach is supported in IE9
exports.forEach = function forEach(xs, fn, self) {
if (xs.forEach) return xs.forEach(fn, self);
for (var i = 0; i < xs.length; i++) {
fn.call(self, xs[i], i, xs);
}
};
// Array.prototype.map is supported in IE9
exports.map = function map(xs, fn) {
if (xs.map) return xs.map(fn);
var out = new Array(xs.length);
for (var i = 0; i < xs.length; i++) {
out[i] = fn(xs[i], i, xs);
}
return out;
};
// Array.prototype.reduce is supported in IE9
exports.reduce = function reduce(array, callback, opt_initialValue) {
if (array.reduce) return array.reduce(callback, opt_initialValue);
var value, isValueSet = false;
if (2 < arguments.length) {
value = opt_initialValue;
isValueSet = true;
}
for (var i = 0, l = array.length; l > i; ++i) {
if (array.hasOwnProperty(i)) {
if (isValueSet) {
value = callback(value, array[i], i, array);
}
else {
value = array[i];
isValueSet = true;
}
}
}
return value;
};
// String.prototype.substr - negative index don't work in IE8
if ('ab'.substr(-1) !== 'b') {
exports.substr = function (str, start, length) {
// did we get a negative start, calculate how much it is from the beginning of the string
if (start < 0) start = str.length + start;
// call the original function
return str.substr(start, length);
};
} else {
exports.substr = function (str, start, length) {
return str.substr(start, length);
};
}
// String.prototype.trim is supported in IE9
exports.trim = function (str) {
if (str.trim) return str.trim();
return str.replace(/^\s+|\s+$/g, '');
};
// Function.prototype.bind is supported in IE9
exports.bind = function () {
var args = Array.prototype.slice.call(arguments);
var fn = args.shift();
if (fn.bind) return fn.bind.apply(fn, args);
var self = args.shift();
return function () {
fn.apply(self, args.concat([Array.prototype.slice.call(arguments)]));
};
};
// Object.create is supported in IE9
function create(prototype, properties) {
var object;
if (prototype === null) {
object = { '__proto__' : null };
}
else {
if (typeof prototype !== 'object') {
throw new TypeError(
'typeof prototype[' + (typeof prototype) + '] != \'object\''
);
}
var Type = function () {};
Type.prototype = prototype;
object = new Type();
object.__proto__ = prototype;
}
if (typeof properties !== 'undefined' && Object.defineProperties) {
Object.defineProperties(object, properties);
}
return object;
}
exports.create = typeof Object.create === 'function' ? Object.create : create;
// Object.keys and Object.getOwnPropertyNames is supported in IE9 however
// they do show a description and number property on Error objects
function notObject(object) {
return ((typeof object != "object" && typeof object != "function") || object === null);
}
function keysShim(object) {
if (notObject(object)) {
throw new TypeError("Object.keys called on a non-object");
}
var result = [];
for (var name in object) {
if (hasOwnProperty.call(object, name)) {
result.push(name);
}
}
return result;
}
// getOwnPropertyNames is almost the same as Object.keys one key feature
// is that it returns hidden properties, since that can't be implemented,
// this feature gets reduced so it just shows the length property on arrays
function propertyShim(object) {
if (notObject(object)) {
throw new TypeError("Object.getOwnPropertyNames called on a non-object");
}
var result = keysShim(object);
if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) {
result.push('length');
}
return result;
}
var keys = typeof Object.keys === 'function' ? Object.keys : keysShim;
var getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ?
Object.getOwnPropertyNames : propertyShim;
if (new Error().hasOwnProperty('description')) {
var ERROR_PROPERTY_FILTER = function (obj, array) {
if (toString.call(obj) === '[object Error]') {
array = exports.filter(array, function (name) {
return name !== 'description' && name !== 'number' && name !== 'message';
});
}
return array;
};
exports.keys = function (object) {
return ERROR_PROPERTY_FILTER(object, keys(object));
};
exports.getOwnPropertyNames = function (object) {
return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object));
};
} else {
exports.keys = keys;
exports.getOwnPropertyNames = getOwnPropertyNames;
}
// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements
function valueObject(value, key) {
return { value: value[key] };
}
if (typeof Object.getOwnPropertyDescriptor === 'function') {
try {
Object.getOwnPropertyDescriptor({'a': 1}, 'a');
exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
} catch (e) {
// IE8 dom element issue - use a try catch and default to valueObject
exports.getOwnPropertyDescriptor = function (value, key) {
try {
return Object.getOwnPropertyDescriptor(value, key);
} catch (e) {
return valueObject(value, key);
}
};
}
} else {
exports.getOwnPropertyDescriptor = valueObject;
}
},{}],6:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// UTILITY
var util = require('util');
var shims = require('_shims');
var pSlice = Array.prototype.slice;
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = module.exports = ok;
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
// actual: actual,
// expected: expected })
assert.AssertionError = function AssertionError(options) {
this.name = 'AssertionError';
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
this.message = options.message || getMessage(this);
};
// assert.AssertionError instanceof Error
util.inherits(assert.AssertionError, Error);
function replacer(key, value) {
if (util.isUndefined(value)) {
return '' + value;
}
if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
return value.toString();
}
if (util.isFunction(value) || util.isRegExp(value)) {
return value.toString();
}
return value;
}
function truncate(s, n) {
if (util.isString(s)) {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
function getMessage(self) {
return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
self.operator + ' ' +
truncate(JSON.stringify(self.expected, replacer), 128);
}
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
function ok(value, message) {
if (!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, '!=', assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
function _deepEqual(actual, expected) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
} else if (util.isBuffer(actual) && util.isBuffer(expected)) {
if (actual.length != expected.length) return false;
for (var i = 0; i < actual.length; i++) {
if (actual[i] !== expected[i]) return false;
}
return true;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (util.isDate(actual) && util.isDate(expected)) {
return actual.getTime() === expected.getTime();
// 7.3 If the expected value is a RegExp object, the actual value is
// equivalent if it is also a RegExp object with the same source and
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
return actual.source === expected.source &&
actual.global === expected.global &&
actual.multiline === expected.multiline &&
actual.lastIndex === expected.lastIndex &&
actual.ignoreCase === expected.ignoreCase;
// 7.4. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
} else if (!util.isObject(actual) && !util.isObject(expected)) {
return actual == expected;
// 7.5 For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
return objEquiv(actual, expected);
}
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b) {
if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
return false;
// an identical 'prototype' property.
if (a.prototype !== b.prototype) return false;
//~~~I've managed to break Object.keys through screwy arguments passing.
// Converting to array solves the problem.
if (isArguments(a)) {
if (!isArguments(b)) {
return false;
}
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b);
}
try {
var ka = shims.keys(a),
kb = shims.keys(b),
key, i;
} catch (e) {//happens when one is a string literal and the other isn't
return false;
}
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
if (ka.length != kb.length)
return false;
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] != kb[i])
return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key])) return false;
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, '===', assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, '!==', assert.notStrictEqual);
}
};
function expectedException(actual, expected) {
if (!actual || !expected) {
return false;
}
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
return expected.test(actual);
} else if (actual instanceof expected) {
return true;
} else if (expected.call({}, actual) === true) {
return true;
}
return false;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (util.isString(expected)) {
message = expected;
expected = null;
}
try {
block();
} catch (e) {
actual = e;
}
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
(message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail(actual, expected, 'Missing expected exception' + message);
}
if (!shouldThrow && expectedException(actual, expected)) {
fail(actual, expected, 'Got unwanted exception' + message);
}
if ((shouldThrow && actual && expected &&
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
throw actual;
}
}
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [true].concat(pSlice.call(arguments)));
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/message) {
_throws.apply(this, [false].concat(pSlice.call(arguments)));
};
assert.ifError = function(err) { if (err) {throw err;}};
},{"_shims":5,"util":7}],7:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var shims = require('_shims');
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
shims.forEach(array, function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = shims.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = shims.getOwnPropertyNames(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
shims.forEach(keys, function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (shims.indexOf(ctx.seen, desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = shims.reduce(output, function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return shims.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) && objectToString(e) === '[object Error]';
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
function isBuffer(arg) {
return arg instanceof Buffer;
}
exports.isBuffer = isBuffer;
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = function(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = shims.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = shims.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
},{"_shims":5}]},{},[])
;;module.exports=require("buffer-browserify")
},{}],7:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
if (ev.source === window && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
throw new Error('process.binding is not supported');
}
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
},{}],8:[function(require,module,exports){
/*
Copyright (c) 2011, Chris Umbel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var FFI = require('node-ffi');
var elementSize = 4;
function fortranArrayToJSMatrix(fortranArray, m, n) {
var array = [];
var a;
var rowWidth = elementSize * n;
var columnOffset = m * elementSize;
for(var i = 0; i < m; i++) {
var row = [];
var rowStart = i * elementSize;
for(var j = 0; j < n; j++) {
a = fortranArray.seek(columnOffset * j + rowStart);
row.push(a.getFloat());
}
array.push(row);
}
return array;
}
function jsMatrixToFortranArray(array) {
var m = array.length;
var n = array[0].length;
var fortranArrayStart = fortranArray = new FFI.Pointer(m * n * elementSize);
for(var j = 0; j < n; j++) {
for(var i = 0; i < m; i++) {
fortranArray.putFloat(array[i][j]);
fortranArray = fortranArray.seek(elementSize);
}
}
return fortranArrayStart;
}
function fortranArrayToJSArray(fortranArray, n) {
var array = [];
for(var i = 0; i < n; i++) {
array.push(fortranArray.getFloat());
fortranArray = fortranArray.seek(elementSize);
}
return array;
}
function fortranIntArrayToJSArray(fortranArray, n) {
var array = [];
for(var i = 0; i < n; i++) {
array.push(fortranArray.getInt32());
fortranArray = fortranArray.seek(4);
}
return array;
}
module.exports.fortranArrayToJSMatrix = fortranArrayToJSMatrix;
module.exports.jsMatrixToFortranArray = jsMatrixToFortranArray;
module.exports.fortranArrayToJSArray = fortranArrayToJSArray;
module.exports.fortranIntArrayToJSArray = fortranIntArrayToJSArray;
},{"node-ffi":15}],9:[function(require,module,exports){
/*
Copyright (c) 2011, Chris Umbel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var lapack = require('./lapack.js');
exports.sgeqrf = lapack.sgeqrf;
exports.sgesvd = lapack.sgesvd;
exports.qr = lapack.qr;
exports.lu = lapack.lu;
exports.sgetrf = lapack.sgetrf;
exports.sgesv = lapack.sgesv;
},{"./lapack.js":10}],10:[function(require,module,exports){
/*
Copyright (c) 2011, Chris Umbel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
var fortranArray = require('./fortranArray');
var FFI = require('node-ffi');
var LAPACK;
try {
LAPACK = new FFI.Library('liblapack', {
"sgeqrf_": ["void", ["pointer", "pointer", "pointer", "pointer", "pointer",
"pointer", "pointer", "pointer"]],
"sorgqr_": ["void", ["pointer", "pointer", "pointer", "pointer", "pointer", "pointer",
"pointer", "pointer", "pointer"]],
"sgesvd_": ["void", ["pointer", "pointer", "pointer", "pointer", "pointer",
"pointer", "pointer", "pointer", "pointer", "pointer",
"pointer", "pointer", "pointer", "pointer", ]],
"sgetrf_": ["void", ["pointer", "pointer", "pointer", "pointer", "pointer", "pointer"]],
"sgesv_": ["void", ["pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer"]]
});
} catch(e) {
console.log("!!! node-lapack requires the native lapack to be built as a shared lib.");
console.log(e);
}
var FORTRAN_INT = 4;
var FORTRAN_CHAR = 1;
var FORTRAN_FLOAT = 4;
function eye(m) {
var matrix = [];
for(var i = 0; i < m; i++) {
var row = [];
matrix.push(row);
for(var j = 0; j < m; j++) {
if(i == j)
row.push(1);
else
row.push(0);
}
}
return matrix;
}
function matrixOp(matrix, callback) {
var m = matrix.length;
var n = matrix[0].length;
var f_m = new FFI.Pointer(FORTRAN_INT);
var f_n = new FFI.Pointer(FORTRAN_INT);
var f_a = fortranArray.jsMatrixToFortranArray(matrix);
var f_lda = new FFI.Pointer(FORTRAN_INT);
f_m.putInt32(m);
f_n.putInt32(n);
f_lda.putInt32(Math.max(1, m));
callback(m, n, f_m, f_n, f_a, f_lda);
}
function zeroBottomLeft(matrix) {
// zero out bottom left forming an upper right triangle matrix
for(var i = 1; i < matrix.length; i++) {
for(var j = 0; j < i && j < matrix[0].length; j++)
matrix[i][j] = 0;
}
return matrix
}
function sgesv(a, b) {
var f_info = new FFI.Pointer(FORTRAN_INT);
var result = {};
matrixOp(a, function(am, an, af_m, af_n, f_a) {
var f_ipiv = new FFI.Pointer(am * FORTRAN_INT);
matrixOp(b, function(bm, bn, bf_m, bf_n, f_b) {
LAPACK.sgesv_(af_m, bf_n, f_a, af_n, f_ipiv, f_b, bf_m, f_info);
result.X = fortranArray.fortranArrayToJSMatrix(f_b, bm, bn);
result.P = ipivToP(bm, fortranArray.fortranIntArrayToJSArray(f_ipiv, bm));
});
});
return result;
}
function qr(matrix) {
var result;
sgeqrf(matrix, function(qr, m, n, f_m, f_n, f_a, f_lda, f_tau, f_work, f_lwork, f_info) {
var f_k = new FFI.Pointer(FORTRAN_INT);
f_k.putInt32(Math.min(m, n));
LAPACK.sorgqr_(f_m, f_n, f_k, f_a, f_lda, f_tau, f_work, f_lwork, f_info);
qr.Q = fortranArray.fortranArrayToJSMatrix(f_a, m, n);
qr.R = zeroBottomLeft(qr.R);
result = qr;
});
return result;
}
function sgeqrf(matrix, callback) {
var qr;
matrixOp(matrix, function(m, n, f_m, f_n, f_a, f_lda) {
var f_tau = new FFI.Pointer(m * n * FORTRAN_FLOAT);
var f_info = new FFI.Pointer(FORTRAN_INT);
var f_lwork = new FFI.Pointer(FORTRAN_INT);
var f_work;
f_lwork.putInt32(-1);
// get optimal size of workspace
f_work = new FFI.Pointer(FORTRAN_INT);
LAPACK.sgeqrf_(f_m, f_n, f_a, f_lda, f_tau, f_work, f_lwork, f_info);
lwork = f_work.getFloat();
// allocate workspace
f_work = new FFI.Pointer(lwork * FORTRAN_FLOAT);
f_lwork.putInt32(lwork);
// perform QR decomp
LAPACK.sgeqrf_(f_m, f_n, f_a, f_lda, f_tau, f_work, f_lwork, f_info);
qr = {
R: fortranArray.fortranArrayToJSMatrix(f_a, m, n),
tau: fortranArray.fortranArrayToJSArray(f_tau, Math.min(m, n))
};
if(callback)
qr = callback(qr, m, n, f_m, f_n, f_a, f_lda, f_tau, f_work, f_lwork, f_info);
});
return qr;
}
function cloneMatrix(matrix, height, width) {
var clone = [];
height = height || matrix.length;
width = width || matrix[0].length;
for(var i = 0; i < height; i++) {
var row = [];
clone.push(row);
for(var j = 0; j < width; j++) {
row.push(matrix[i][j]);
}
}
return clone;
}
function swapRows(matrix, i, j) {
var tmp = matrix[j];
matrix[j] = matrix[i];
matrix[i] = tmp;
return matrix;
}
function lu(matrix) {
var result = sgetrf(matrix);
var P = ipivToP(matrix.length, result.IPIV);
var L = cloneMatrix(result.LU);
var m = n = Math.min(matrix.length, matrix[0].length);
for(var i = 0; i < L.length; i++) {
for(var j = i; j < L[i].length; j++) {
if(i == j)
L[i][j] = 1;
else
L[i][j] = 0;
}
}
return {
L: L,
U: zeroBottomLeft(cloneMatrix(result.LU, n, n)),
P: P,
IPIV: result.IPIV
};
}
function ipivToP(m, ipiv){
var P = eye(m);
for(var i = 0; i < ipiv.length; i++) {
if(i != ipiv[i] - 1)
swapRows(P, i, ipiv[i] - 1);
}
return P;
}
function sgetrf(matrix) {
var result = {};
matrixOp(matrix, function(m, n, f_m, f_n, f_a, f_lda) {
var f_ipiv = new FFI.Pointer(Math.min(m, n) * FORTRAN_INT);
var f_info = new FFI.Pointer(FORTRAN_INT);
LAPACK.sgetrf_(f_m, f_n, f_a, f_m, f_ipiv, f_info);
result.LU = fortranArray.fortranArrayToJSMatrix(f_a, m, n);
result.IPIV = fortranArray.fortranIntArrayToJSArray(f_ipiv, Math.min(m, n));
});
return result;
}
function sgesvd(jobu, jobvt, matrix) {
var f_jobu = new FFI.Pointer(FORTRAN_CHAR);
var f_jobvt = new FFI.Pointer(FORTRAN_CHAR);
f_jobu.putChar(jobu.charCodeAt(0));
f_jobvt.putChar(jobvt.charCodeAt(0));
var svd;
matrixOp(matrix, function(m, n, f_m, f_n, f_a, f_lda) {
var f_s = new FFI.Pointer(Math.pow(Math.min(m, n), 2) * FORTRAN_FLOAT);
var f_u = new FFI.Pointer(Math.pow(m, 2) * FORTRAN_FLOAT);
var f_ldu = new FFI.Pointer(FORTRAN_INT);
f_ldu.putInt32(m);
// TODO: punting on dims for now. revisit with http://www.netlib.org/lapack/single/sgesvd.f
var f_vt = new FFI.Pointer(Math.pow(n, 2) * FORTRAN_FLOAT);
var f_ldvt = new FFI.Pointer(FORTRAN_INT);
f_ldvt.putInt32(n);
var lwork = -1;
var f_work = new FFI.Pointer(FORTRAN_FLOAT);
var f_lwork = new FFI.Pointer(FORTRAN_INT);
f_lwork.putInt32(lwork);
var f_info = new FFI.Pointer(FORTRAN_INT);
LAPACK.sgesvd_(f_jobu, f_jobvt, f_m, f_n, f_a, f_lda, f_s, f_u, f_ldu, f_vt, f_ldvt,
f_work, f_lwork, f_info);
lwork = f_work.getFloat();
f_work = new FFI.Pointer(lwork * FORTRAN_FLOAT);
f_lwork.putInt32(lwork);
LAPACK.sgesvd_(f_jobu, f_jobvt, f_m, f_n, f_a, f_lda, f_s, f_u, f_ldu, f_vt, f_ldvt,
f_work, f_lwork, f_info);
svd = {
U: fortranArray.fortranArrayToJSMatrix(f_u, m, m),
S: fortranArray.fortranArrayToJSMatrix(f_s, n, n),
VT: fortranArray.fortranArrayToJSMatrix(f_vt, n, n)
};
});
return svd;
}
exports.sgeqrf = sgeqrf;
exports.sgesvd = sgesvd;
exports.sgetrf = sgetrf;
exports.sgesv = sgesv;
exports.qr = qr;
exports.lu = lu;
},{"./fortranArray":8,"node-ffi":15}],11:[function(require,module,exports){
var ffi = require('./ffi')
/**
* Turns a JavaScript function into a C function pointer.
* The function pointer may be used in other C functions that
* accept C callback functions.
* TODO: Deprecate this class, make this function return the callback pointer
* directly.
*/
function Callback (typedata, func) {
var retType = typedata[0]
, types = typedata[1]
this._cif = new ffi.CIF(retType, types)
this._info = new ffi.CallbackInfo(this._cif.getPointer(), function (retval, params) {
var pptr = params.clone()
var args = types.map(function (type) {
return ffi.derefValuePtr(type, pptr.getPointer(true))
})
// Invoke the user-given function
var result = func.apply(null, args)
if (retType !== 'void') {
retval['put' + ffi.TYPE_TO_POINTER_METHOD_MAP[retType]](result)
}
})
this.pointer = this._info.pointer
}
module.exports = Callback
/**
* Returns the callback function pointer. Deprecated. Use `callback.pointer`
* instead.
*/
Callback.prototype.getPointer = function getPointer () {
return this.pointer
}
},{"./ffi":15}],12:[function(require,module,exports){
var ffi = require('./ffi')
/**
* CIF provides a JS interface for the libffi "callback info" (CIF) structure.
* TODO: Deprecate this class. Turn this into a simple function that returns the
* CIF pointer.
*/
function CIF (rtype, types) {
if (!ffi.isValidReturnType(rtype)) {
throw new Error('Invalid Return Type: ' + rtype)
}
var numArgs = types.length
this._argtypesptr = new ffi.Pointer(types.length * ffi.Bindings.FFI_TYPE_SIZE)
this._rtypeptr = ffi.ffiTypeFor(rtype)
var tptr = this._argtypesptr.clone()
for (var i=0; i<numArgs; i++) {
var typeName = types[i]
if (!ffi.isValidParamType(typeName)) {
throw new Error('Invalid Type: ' + typeName)
}
var ffiType = ffi.ffiTypeFor(typeName)
tptr.putPointer(ffiType, true)
}
this.pointer = ffi.Bindings.prepCif(numArgs, this._rtypeptr, this._argtypesptr)
}
module.exports = CIF
CIF.prototype.getPointer = function () { return this.pointer }
},{"./ffi":15}],13:[function(require,module,exports){
var ffi = require('./ffi')
, read = require('fs').readFileSync
, dlopen = ffi.ForeignFunction(ffi.Bindings.StaticFunctions.dlopen
, 'pointer', [ 'string', 'int32' ])
, dlclose = ffi.ForeignFunction(ffi.Bindings.StaticFunctions.dlclose
, 'int32', [ 'pointer' ])
, dlsym = ffi.ForeignFunction(ffi.Bindings.StaticFunctions.dlsym
, 'pointer', [ 'pointer', 'string' ])
, dlerror = ffi.ForeignFunction(ffi.Bindings.StaticFunctions.dlerror
, 'string', [ ])
/**
* `DynamicLibrary` loads and fetches function pointers for dynamic libraries
* (.so, .dylib, etc). After the libray's function pointer is acquired, then you
* call `get(symbol)` to retreive a pointer to an exported symbol. You need to
* call `get___()` on the pointer to dereference it into it's acutal value, or
* turn the pointer into a callable function with `ForeignFunction`.
*/
function DynamicLibrary (path, mode) {
this._handle = dlopen(path, mode || DynamicLibrary.FLAGS.RTLD_NOW)
if (this._handle.isNull()) {
var err = this.error()
// THIS CODE IS BASED ON GHC Trac ticket #2615
// http://hackage.haskell.org/trac/ghc/attachment/ticket/2615
// On some systems (e.g., Gentoo Linux) dynamic files (e.g. libc.so)
// contain linker scripts rather than ELF-format object code. This
// code handles the situation by recognizing the real object code
// file name given in the linker script.
// If an "invalid ELF header" error occurs, it is assumed that the
// .so file contains a linker script instead of ELF object code.
// In this case, the code looks for the GROUP ( ... ) linker
// directive. If one is found, the first file name inside the
// parentheses is treated as the name of a dynamic library and the
// code attempts to dlopen that file. If this is also unsuccessful,
// an error message is returned.
// see if the error message is due to an invalid ELF header
var match
if (match = err.match(/^(([^ \t()])+\.so([^ \t:()])*):([ \t])*invalid ELF header$/)) {
var content = read(match[1], 'ascii')
// try to find a GROUP ( ... ) command
if (match = content.match(/GROUP *\( *(([^ )])+)/)){
return DynamicLibrary.call(this, match[1], mode)
}
}
throw new Error('Dynamic Linking Error: ' + err)
}
}
module.exports = DynamicLibrary
DynamicLibrary.FLAGS = {
'RTLD_LAZY': 0x1
, 'RTLD_NOW': 0x2
, 'RTLD_LOCAL': 0x4
, 'RTLD_GLOBAL': 0x8
}
/**
* Close this library, returns the result of the dlclose() system function.
*/
DynamicLibrary.prototype.close = function () {
return dlclose(this._handle)
}
/**
* Get a symbol from this library, returns a Pointer for (memory address of) the symbol
*/
DynamicLibrary.prototype.get = function (symbol) {
var ptr = dlsym(this._handle, symbol)
if (ptr.isNull()) {
throw new Error('Dynamic Symbol Retrieval Error: ' + this.error())
}
return ptr
}
/**
* Returns the result of the dlerror() system function
*/
DynamicLibrary.prototype.error = function error () {
return dlerror()
}
},{"./ffi":15,"fs":3}],14:[function(require,module,exports){
var process=require("__browserify_process");
/**
* Implementation of errno. This is a #define :/
* On Linux, it's a global variable with the symbol `errno`,
* but on Darwin it's a method execution called `__error`.
*/
var ffi = require('./ffi')
, errnoPtr = null
if (process.platform == 'darwin' || process.platform == 'mac') {
var __error = new ffi.DynamicLibrary().get('__error')
errnoPtr = ffi.ForeignFunction(__error, 'pointer', [])
} else if (process.platform == 'win32') {
var _errno = new ffi.DynamicLibrary('msvcrt.dll').get('_errno')
errnoPtr = ffi.ForeignFunction(_errno, 'pointer', [])
} else {
var errnoGlobal = new ffi.DynamicLibrary().get('errno');
errnoPtr = function () { return errnoGlobal }
}
function errno () {
return errnoPtr().getInt32()
}
module.exports = errno
},{"./ffi":15,"__browserify_process":7}],15:[function(require,module,exports){
var ffi = module.exports
ffi.Bindings = require('bindings')('ffi_bindings.node')
ffi.VERSION = '0.5.0'
ffi.TYPE_TO_POINTER_METHOD_MAP = {
'uint8': 'UInt8'
, 'int8': 'Int8'
, 'uint8': 'UInt8'
, 'int16': 'Int16'
, 'uint16': 'UInt16'
, 'int32': 'Int32'
, 'uint32': 'UInt32'
, 'int64': 'Int64'
, 'uint64': 'UInt64'
, 'float': 'Float'
, 'double': 'Double'
, 'string': 'CString'
, 'pointer': 'Pointer'
}
ffi.SIZE_TO_POINTER_METHOD_MAP = {
1: 'Int8'
, 2: 'Int16'
, 4: 'Int32'
, 8: 'Int64'
}
ffi.PLATFORM_LIBRARY_EXTENSIONS = {
'linux': '.so'
, 'linux2': '.so'
, 'sunos': '.so'
, 'solaris':'.so'
, 'darwin': '.dylib'
, 'mac': '.dylib'
, 'win32': '.dll'
}
// A list of types with no hard C++ methods to read/write them
ffi.NON_SPECIFIC_TYPES = {
'byte': 'Byte'
, 'char': 'Char'
, 'uchar': 'UChar'
, 'short': 'Short'
, 'ushort': 'UShort'
, 'int': 'Int'
, 'uint': 'UInt'
, 'long': 'Long'
, 'ulong': 'ULong'
, 'longlong': 'LongLong'
, 'ulonglong': 'ULongLong'
, 'size_t': 'SizeT'
}
// ------------------------------------------------------
// Miscellaneous Utility Functions
// ------------------------------------------------------
// Returns true if the passed type is a valid param type
ffi.isValidParamType = function(type) {
return ffi.isStructType(type) || ffi.Bindings.FFI_TYPES[type] != undefined
}
// Returns true if the passed type is a valid return type
ffi.isValidReturnType = function(type) {
return ffi.isValidParamType(type) || type == 'void'
}
ffi.derefValuePtr = function(type, ptr) {
if (!ffi.isValidParamType(type)) {
throw new Error('Invalid Type: ' + type)
}
if (ffi.isStructType(type)) {
return new type(ptr)
}
if (type == 'void') {
return null
}
var dptr = ptr
if (type == 'string') {
dptr = ptr.getPointer()
if (dptr.isNull()) {
return null
}
}
return dptr['get' + ffi.TYPE_TO_POINTER_METHOD_MAP[type]]()
}
// Generates a derefValuePtr for a specific type
ffi.derefValuePtrFunc = function(type) {
if (!ffi.isValidParamType(type)) {
throw new Error('Invalid Type: ' + type)
}
if (ffi.isStructType(type)) {
return function(ptr) {
return new type(ptr)
}
}
if (type == 'void') {
return function(ptr) { return null; }
}
var getf = 'get' + ffi.TYPE_TO_POINTER_METHOD_MAP[type]
if (type == 'string') {
return function(ptr) {
var dptr = ptr.getPointer()
if (dptr.isNull()) {
return null
}
return dptr[getf]()
}
} else {
return function(ptr) {
return ptr[getf]()
}
}
}
/**
* Returns the byte size of the given type. `type` may be a string name
* identifier or a Struct type.
* Roughly equivalent to the C sizeof() operator.
*/
function sizeof (type) {
return ffi.isStructType(type)
? type.__structInfo__.size
: ffi.Bindings.TYPE_SIZE_MAP[type]
}
ffi.sizeOf = ffi.sizeof = sizeof
/**
* Returns the FFI_TYPE for the given `type`. May be a `Struct` type.
*/
function ffiTypeFor (type) {
return ffi.isStructType(type)
? type._ffiType().ref()
: ffi.Bindings.FFI_TYPES[type]
}
ffi.ffiTypeFor = ffiTypeFor
/**
* Returns true if the given `type` is a Struct type, false otherwise.
*/
function isStructType (type) {
return !!type.__isStructType__
}
ffi.isStructType = isStructType
// Direct exports from the bindings
ffi.free = ffi.Bindings.free
ffi.CallbackInfo = ffi.Bindings.CallbackInfo
// Include our other modules
ffi.Pointer = require('./pointer')
ffi.CIF = require('./cif')
ffi.ForeignFunction = require('./foreign_function')
ffi.DynamicLibrary = require('./dynamic_library')
ffi.Library = require('./library')
ffi.Callback = require('./callback')
ffi.Struct = require('./struct')
ffi.errno = require('./errno')
/**
* Define the `FFI_TYPE` struct for use in JS.
* This struct type is used internally to define custom struct rtn/arg types.
*/
ffi.FFI_TYPE = ffi.Struct([
['size_t', 'size']
, ['ushort', 'alignment']
, ['ushort', 'type']
, ['pointer','elements']
])
},{"./callback":11,"./cif":12,"./dynamic_library":13,"./errno":14,"./foreign_function":16,"./library":17,"./pointer":18,"./struct":19,"bindings":20}],16:[function(require,module,exports){
var Buffer=require("__browserify_Buffer").Buffer;var ffi = require('./ffi')
, EventEmitter = require('events').EventEmitter
, POINTER_SIZE = ffi.Bindings.POINTER_SIZE
/**
* Represents a foreign function in another library. Manages all of the aspects
* of function execution, including marshalling the data parameters for the
* function into native types and also unmarshalling the return from function
* execution.
*/
function ForeignFunction (ptr, returnType, types, async) {
if (!(this instanceof ForeignFunction)) {
return new ForeignFunction(ptr, returnType, types, async)
}
var self = this
, numArgs = types.length
, drefVal = ffi.derefValuePtrFunc(returnType)
, result = new ffi.Pointer(ffi.sizeOf(returnType))
, argsList = new ffi.Pointer(numArgs * POINTER_SIZE)
, cif = new ffi.CIF(returnType, types)
, caller = new ffi.Bindings.ForeignCaller(
cif.getPointer()
, ptr
, argsList
, result
, async
)
// XXX: Can't remove or shit segsaults... WTF....
this._ = cif
// allocate a storage area for each argument,
// then write the pointer to the argument list
var argputf = types.map(function (type, i) {
var argPtr = argsList.seek(i * POINTER_SIZE)
if (ffi.isStructType(type)) {
return function (val) {
argPtr.putPointer(val.ref())
}
}
var valPtr = new ffi.Pointer(ffi.sizeOf(type))
argPtr.putPointer(valPtr)
if (type == 'string') {
return function (val) {
var ptr = ffi.Pointer.NULL
if (typeof val !== 'undefined' && val !== null) {
var len = Buffer.byteLength(val, 'utf8')
ptr = new ffi.Pointer(len+1)
ptr.putCString(val)
}
valPtr.putPointer(ptr)
}
} else if (type == 'pointer') {
// Bypass the struct check for non-struct types
return function (val) {
valPtr._putPointer(val)
}
} else {
// Generic type putter function
var putCall = 'put' + ffi.TYPE_TO_POINTER_METHOD_MAP[type]
return function (val) {
valPtr[putCall](val)
}
}
})
var proxy = function () {
self // XXX: if this isn't in here, callbacks segfault. what.. the.. f?
if (arguments.length !== numArgs) {
throw new Error('Function arguments did not meet specification')
}
// write arguments to storage areas
for (var i=0; i<numArgs; i++) {
argputf[i](arguments[i])
}
var r = caller.exec()
if (async) {
var emitter = new EventEmitter()
r.on('success', function () {
emitter.emit('success', drefVal(result))
})
return emitter
}
return drefVal(result)
}
// Backwards compat
// XXX: Remove soon...
proxy.getFunction = function () { return this }
return proxy
}
module.exports = ForeignFunction
/**
* Deprecated. Just invoke ForeignFunction() instead.
*/
ForeignFunction.build = ForeignFunction
},{"./ffi":15,"__browserify_Buffer":6,"events":2}],17:[function(require,module,exports){
var process=require("__browserify_process");var ffi = require('./ffi')
, EXT = ffi.PLATFORM_LIBRARY_EXTENSIONS[process.platform]
, RTLD_NOW = ffi.DynamicLibrary.FLAGS.RTLD_NOW
/**
* Provides a friendly abstraction/API on-top of DynamicLibrary and
* ForeignFunction.
*/
function Library (libfile, funcs) {
if (libfile && libfile.indexOf(EXT) === -1) {
libfile += EXT
}
var lib = {}
, dl = new ffi.DynamicLibrary(libfile || null, RTLD_NOW)
if (funcs) {
Object.keys(funcs).forEach(function (func) {
var fptr = dl.get(func)
, info = funcs[func]
if (fptr.isNull()) {
throw new Error('DynamicLibrary "'+libfile+'" returned NULL function pointer for "'+func+'"')
}
var resultType = info[0]
, paramTypes = info[1]
, fopts = info[2]
, async = fopts ? fopts.async : false
lib[func] = ffi.ForeignFunction(fptr, resultType, paramTypes, async)
})
}
return lib
}
module.exports = Library
},{"./ffi":15,"__browserify_process":7}],18:[function(require,module,exports){
var Buffer=require("__browserify_Buffer").Buffer;var ffi = require('./ffi')
, util = require('util')
, Pointer = module.exports = ffi.Bindings.Pointer
/**
* `attach()` is used for tracking dependencies among pointers to prevent
* garbage collection.
*/
Pointer.prototype.attach = function attach (friend) {
if (!Array.isArray(friend.__attached)) {
friend.__attached = []
}
friend.__attached.push(this)
}
/**
* Creates and returns a new Pointer that points to the same `address` as this
* pointer. Usefor for when you want to use a pointer as in iterator, but still
* want to retain this original pointer's address for use.
*
* The returned Pointer's `free` variable is set to `false` by default.
*
* @return {Pointer} A new Pointer independent of this one, but points to the same `address`.
*/
Pointer.prototype.clone = function clone () {
return this.seek(0)
}
/**
* This wraps _putPointer so it supports direct Struct writing.
*/
Pointer.prototype.putPointer = function putPointer (ptr, seek) {
var p = ptr && 'pointer' in ptr ? ptr.pointer : ptr
return this._putPointer(p, seek)
}
/**
* Custom inspect() function for easier inspecting of Pointers in the REPL
*/
Pointer.prototype.inspect = function inspect (depth, hidden, colors) {
return '<Pointer address="'
+ util.inspect(this.address, hidden, depth - 1, colors)
+'" allocated="'
+ util.inspect(this.allocated, hidden, depth - 1, colors)
+'" free="'
+ util.inspect(this.free, hidden, depth - 1, colors)
+'">'
}
/**
* Returns `true` if the given argument is a `Pointer` instance.
* Returns `false` otherwise.
*
* @param {Object} p A pointer object (possibly...)
* @return {Boolean} `true` if the object is a `Pointer` instance
*/
Pointer.isPointer = function isPointer (p) {
return p instanceof Pointer
}
/**
* Allocates a pointer big enough to fit *type* and *value*, writes the value,
* and returns it.
*/
Pointer.alloc = function alloc (type, value) {
var size = type == 'string'
? Buffer.byteLength(value, 'utf8') + 1
: ffi.sizeOf(type)
// malloc() the buffer
var ptr = new Pointer(size)
// write the value
ptr['put' + ffi.TYPE_TO_POINTER_METHOD_MAP[type]](value)
if (type == 'string') {
// XXX: consider removing this string special case. it's dumb.
// we have to actually build an "in-between" pointer for strings
var dptr = new ffi.Pointer(ffi.Bindings.TYPE_SIZE_MAP.pointer)
ptr.attach(dptr) // save it from garbage collection
dptr.putPointer(ptr)
return dptr
}
return ptr
}
/**
* Appends the `NON_SPECIFIC_TYPES` to the `TYPE_TO_POINTER_METHOD_MAP` by
* discovering the method suffix by type size.
*/
Object.keys(ffi.NON_SPECIFIC_TYPES).forEach(function (type) {
var method = ffi.NON_SPECIFIC_TYPES[type]
, suffix = ffi.TYPE_TO_POINTER_METHOD_MAP[type]
if (!suffix) {
// No hard mapping, determine by size
var size = ffi.sizeOf(type)
, szFunc = ffi.SIZE_TO_POINTER_METHOD_MAP[size]
, signed = type !== 'byte' && type != 'size_t' && type[0] != 'u'
suffix = (signed ? '' : 'U') + szFunc
}
ffi.TYPE_TO_POINTER_METHOD_MAP[type] = suffix
Pointer.prototype['put' + method] = Pointer.prototype['put' + suffix]
Pointer.prototype['get' + method] = Pointer.prototype['get' + suffix]
})
/**
* Define the `NULL` pointer. Used internally in other parts of node-ffi.
*/
Pointer.NULL = new Pointer(0)
},{"./ffi":15,"__browserify_Buffer":6,"util":5}],19:[function(require,module,exports){
var Buffer=require("__browserify_Buffer").Buffer;var ffi = require('./ffi')
/**
* An interface for modeling and instantiating C-style data structures. This is
* not a constructor per-say, but a constructor generator. It takes an array of
* tuples, the left side being the type, and the right side being a field name.
* The order should be the same order it would appear in the C-style struct
* definition. It returns a function that can be used to construct an object that
* reads and writes to the data structure using properties specified by the
* initial field list.
*
* Example:
*
* var PasswordEntry = ffi.Struct(
* ['string', 'username']
* , ['string', 'password']
* )
* var pwd = new PasswordEntry()
* pwd.username = 'ricky'
* pwd.password = 'rbransonlovesnode.js'
*/
function Struct () {
var struct = {}
, fields = arguments
// Legacy API, pass an Array of Arrays
if (arguments.length > 0) {
var firstArg = arguments[0]
if (Array.isArray(firstArg) && firstArg.length > 0 && Array.isArray(firstArg[0])) {
fields = firstArg
}
}
struct.struct = {}
struct.members = []
struct.size = 0
struct.alignment = 0
function read (ptr, name) {
var info = struct.struct[name]
var fptr = ptr.seek(info.offset)
if (ffi.isStructType(info.type)) {
return new info.type(fptr)
} else if (info.type == 'string') {
return fptr.getPointer().getCString()
} else {
return fptr['get' + ffi.TYPE_TO_POINTER_METHOD_MAP[info.type]]()
}
}
function write (ptr, name, val) {
var info = struct.struct[name]
var fptr = ptr.seek(info.offset)
if (ffi.isStructType(info.type)) {
new info.type(fptr, val)
} else if (info.type == 'string') {
if (typeof val == 'undefined' || val === null) {
return fptr.putPointer(ffi.Pointer.NULL)
}
var len = Buffer.byteLength(val, 'utf8')
var strPtr = new ffi.Pointer(len+1)
strPtr.putCString(val)
fptr.putPointer(strPtr)
} else {
return fptr['put' + ffi.TYPE_TO_POINTER_METHOD_MAP[info.type]](val)
}
}
// Read the fields list and apply all the fields to the struct
for (var i=0, len=fields.length; i<len; i++) {
var field = fields[i]
, type = field[0]
, name = field[1]
//console.log(name)
if (name in struct.struct) {
throw new Error('Error when constructing Struct: ' + name + ' field specified twice!')
}
var stype = ffi.isStructType(type)
, sz = ffi.sizeOf(type)
, asz = stype ? type.__structInfo__.alignment : sz
//console.log(' size:',sz)
//console.log(' offset:', struct.size)
//console.log(' asz:',asz)
struct.alignment = Math.max(struct.alignment, asz)
var left = struct.size % struct.alignment
, offset = struct.size
if (sz > left) {
offset += left
}
struct.size = offset + sz
struct.struct[name] = {
name: name
, type: type
, size: sz
, offset: offset
}
struct.members.push(name)
}
//console.log('before left:', struct.size, struct.alignment)
var left = struct.size % struct.alignment
if (left) {
struct.size += struct.alignment - left
}
//console.log('after left:', struct.size)
var constructor = function (arg, data) {
if (!(this instanceof constructor)) {
return new constructor(arg, data)
}
if (ffi.Pointer.isPointer(arg)) {
this.pointer = arg
arg = data
} else {
this.pointer = new ffi.Pointer(struct.size)
}
if (arg) {
for (var key in arg) {
write(this.pointer, key, arg[key])
}
}
}
// Function to return an `FFI_TYPE` struct instance from this struct
constructor._ffiType = function ffiType () {
// return cached if available
if (this._ffiTypeCached) {
return this._ffiTypeCached
}
var props = this.__structInfo__.struct
, propNames = Object.keys(props)
, numProps = propNames.length
var t = new ffi.FFI_TYPE()
t.size = 0
t.alignment = 0
t.type = 13 // FFI_TYPE_STRUCT
t.elements = new ffi.Pointer(ffi.Bindings.POINTER_SIZE * (numProps+1))
var tptr = t.elements.clone()
for (var i=0; i<numProps; i++) {
var prop = props[propNames[i]]
tptr.putPointer(ffi.ffiTypeFor(prop.type), true)
}
// Final NULL pointer to terminate the Array
tptr.putPointer(ffi.Pointer.NULL)
return this._ffiTypeCached = t
}
// Add getters & setters for each field to the constructor's prototype
struct.members.forEach(function (field) {
Object.defineProperty(constructor.prototype, field, {
get: function () {
return read(this.pointer, field)
}
, set: function (val) {
write(this.pointer, field, val)
}
, enumerable: true
, configurable: true
})
})
constructor.prototype.__isStructInstance__ == true
constructor.prototype.__structInfo__ = struct
constructor.prototype.ref = function ref () {
return this.pointer
}
constructor.__isStructType__ = true
constructor.__structInfo__ = struct
return constructor
}
module.exports = Struct
},{"./ffi":15,"__browserify_Buffer":6}],20:[function(require,module,exports){
var process=require("__browserify_process"),__filename="/../../../lapack/node_modules/node-ffi/node_modules/bindings/bindings.js";
/**
* Module dependencies.
*/
var fs = require('fs')
, path = require('path')
, join = path.join
, dirname = path.dirname
, exists = fs.existsSync || path.existsSync
, defaults = {
arrow: process.env.NODE_BINDINGS_ARROW || ' → '
, compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled'
, platform: process.platform
, arch: process.arch
, version: process.versions.node
, bindings: 'bindings.node'
, try: [
// node-gyp's linked version in the "build" dir
[ 'module_root', 'build', 'bindings' ]
// node-waf and gyp_addon (a.k.a node-gyp)
, [ 'module_root', 'build', 'Debug', 'bindings' ]
, [ 'module_root', 'build', 'Release', 'bindings' ]
// Debug files, for development (legacy behavior, remove for node v0.9)
, [ 'module_root', 'out', 'Debug', 'bindings' ]
, [ 'module_root', 'Debug', 'bindings' ]
// Release files, but manually compiled (legacy behavior, remove for node v0.9)
, [ 'module_root', 'out', 'Release', 'bindings' ]
, [ 'module_root', 'Release', 'bindings' ]
// Legacy from node-waf, node <= 0.4.x
, [ 'module_root', 'build', 'default', 'bindings' ]
// Production "Release" buildtype binary (meh...)
, [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ]
]
}
/**
* The main `bindings()` function loads the compiled bindings for a given module.
* It uses V8's Error API to determine the parent filename that this function is
* being invoked from, which is then used to find the root directory.
*/
function bindings (opts) {
// Argument surgery
if (typeof opts == 'string') {
opts = { bindings: opts }
} else if (!opts) {
opts = {}
}
opts.__proto__ = defaults
// Get the module root
if (!opts.module_root) {
opts.module_root = exports.getRoot(exports.getFileName())
}
// Ensure the given bindings name ends with .node
if (path.extname(opts.bindings) != '.node') {
opts.bindings += '.node'
}
var tries = []
, i = 0
, l = opts.try.length
, n
, b
, err
for (; i<l; i++) {
n = join.apply(null, opts.try[i].map(function (p) {
return opts[p] || p
}))
tries.push(n)
try {
b = opts.path ? require.resolve(n) : require(n)
if (!opts.path) {
b.path = n
}
return b
} catch (e) {
if (!/not find/i.test(e.message)) {
throw e
}
}
}
err = new Error('Could not locate the bindings file. Tried:\n'
+ tries.map(function (a) { return opts.arrow + a }).join('\n'))
err.tries = tries
throw err
}
module.exports = exports = bindings
/**
* Gets the filename of the JavaScript file that invokes this function.
* Used to help find the root directory of a module.
*/
exports.getFileName = function getFileName () {
var origPST = Error.prepareStackTrace
, origSTL = Error.stackTraceLimit
, dummy = {}
, fileName
Error.stackTraceLimit = 10
Error.prepareStackTrace = function (e, st) {
for (var i=0, l=st.length; i<l; i++) {
fileName = st[i].getFileName()
if (fileName !== __filename) {
return
}
}
}
// run the 'prepareStackTrace' function above
Error.captureStackTrace(dummy)
dummy.stack
// cleanup
Error.prepareStackTrace = origPST
Error.stackTraceLimit = origSTL
return fileName
}
/**
* Gets the root directory of a module, given an arbitrary filename
* somewhere in the module tree. The "root directory" is the directory
* containing the `package.json` file.
*
* In: /home/nate/node-native-module/lib/index.js
* Out: /home/nate/node-native-module
*/
exports.getRoot = function getRoot (file) {
var dir = dirname(file)
, prev
while (true) {
if (dir === '.') {
// Avoids an infinite loop in rare cases, like the REPL
dir = process.cwd()
}
if (exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules'))) {
// Found the 'package.json' file or 'node_modules' dir; we're done
return dir
}
if (prev === dir) {
// Got to the top
throw new Error('Could not find module root given file: "' + file
+ '". Do you have a `package.json` file? ')
}
// Try the parent dir next
prev = dir
dir = join(dir, '..')
}
}
},{"__browserify_process":7,"fs":3,"path":4}],"sylvester":[function(require,module,exports){
module.exports=require('u9I67l');
},{}],"u9I67l":[function(require,module,exports){
var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};// Copyright (c) 2011, Chris Umbel
exports.Vector = require('./vector');
global.$V = exports.Vector.create;
exports.Matrix = require('./matrix');
global.$M = exports.Matrix.create;
exports.Line = require('./line');
global.$L = exports.Line.create;
exports.Plane = require('./plane');
global.$P = exports.Plane.create;
exports.Line.Segment = require('./line.segment');
exports.Sylvester = require('./sylvester');
},{"./line":23,"./line.segment":24,"./matrix":25,"./plane":26,"./sylvester":27,"./vector":28}],23:[function(require,module,exports){
// Copyright (c) 2011, Chris Umbel, James Coglan
var Vector = require('./vector');
var Matrix = require('./matrix');
var Plane = require('./plane');
var Sylvester = require('./sylvester');
// Line class - depends on Vector, and some methods require Matrix and Plane.
function Line() {}
Line.prototype = {
// Returns true if the argument occupies the same space as the line
eql: function(line) {
return (this.isParallelTo(line) && this.contains(line.anchor));
},
// Returns a copy of the line
dup: function() {
return Line.create(this.anchor, this.direction);
},
// Returns the result of translating the line by the given vector/array
translate: function(vector) {
var V = vector.elements || vector;
return Line.create([
this.anchor.elements[0] + V[0],
this.anchor.elements[1] + V[1],
this.anchor.elements[2] + (V[2] || 0)
], this.direction);
},
// Returns true if the line is parallel to the argument. Here, 'parallel to'
// means that the argument's direction is either parallel or antiparallel to
// the line's own direction. A line is parallel to a plane if the two do not
// have a unique intersection.
isParallelTo: function(obj) {
if (obj.normal || (obj.start && obj.end)) { return obj.isParallelTo(this); }
var theta = this.direction.angleFrom(obj.direction);
return (Math.abs(theta) <= Sylvester.precision || Math.abs(theta - Math.PI) <= Sylvester.precision);
},
// Returns the line's perpendicular distance from the argument,
// which can be a point, a line or a plane
distanceFrom: function(obj) {
if (obj.normal || (obj.start && obj.end)) { return obj.distanceFrom(this); }
if (obj.direction) {
// obj is a line
if (this.isParallelTo(obj)) { return this.distanceFrom(obj.anchor); }
var N = this.direction.cross(obj.direction).toUnitVector().elements;
var A = this.anchor.elements, B = obj.anchor.elements;
return Math.abs((A[0] - B[0]) * N[0] + (A[1] - B[1]) * N[1] + (A[2] - B[2]) * N[2]);
} else {
// obj is a point
var P = obj.elements || obj;
var A = this.anchor.elements, D = this.direction.elements;
var PA1 = P[0] - A[0], PA2 = P[1] - A[1], PA3 = (P[2] || 0) - A[2];
var modPA = Math.sqrt(PA1*PA1 + PA2*PA2 + PA3*PA3);
if (modPA === 0) return 0;
// Assumes direction vector is normalized
var cosTheta = (PA1 * D[0] + PA2 * D[1] + PA3 * D[2]) / modPA;
var sin2 = 1 - cosTheta*cosTheta;
return Math.abs(modPA * Math.sqrt(sin2 < 0 ? 0 : sin2));
}
},
// Returns true iff the argument is a point on the line, or if the argument
// is a line segment lying within the receiver
contains: function(obj) {
if (obj.start && obj.end) { return this.contains(obj.start) && this.contains(obj.end); }
var dist = this.distanceFrom(obj);
return (dist !== null && dist <= Sylvester.precision);
},
// Returns the distance from the anchor of the given point. Negative values are
// returned for points that are in the opposite direction to the line's direction from
// the line's anchor point.
positionOf: function(point) {
if (!this.contains(point)) { return null; }
var P = point.elements || point;
var A = this.anchor.elements, D = this.direction.elements;
return (P[0] - A[0]) * D[0] + (P[1] - A[1]) * D[1] + ((P[2] || 0) - A[2]) * D[2];
},
// Returns true iff the line lies in the given plane
liesIn: function(plane) {
return plane.contains(this);
},
// Returns true iff the line has a unique point of intersection with the argument
intersects: function(obj) {
if (obj.normal) { return obj.intersects(this); }
return (!this.isParallelTo(obj) && this.distanceFrom(obj) <= Sylvester.precision);
},
// Returns the unique intersection point with the argument, if one exists
intersectionWith: function(obj) {
if (obj.normal || (obj.start && obj.end)) { return obj.intersectionWith(this); }
if (!this.intersects(obj)) { return null; }
var P = this.anchor.elements, X = this.direction.elements,
Q = obj.anchor.elements, Y = obj.direction.elements;
var X1 = X[0], X2 = X[1], X3 = X[2], Y1 = Y[0], Y2 = Y[1], Y3 = Y[2];
var PsubQ1 = P[0] - Q[0], PsubQ2 = P[1] - Q[1], PsubQ3 = P[2] - Q[2];
var XdotQsubP = - X1*PsubQ1 - X2*PsubQ2 - X3*PsubQ3;
var YdotPsubQ = Y1*PsubQ1 + Y2*PsubQ2 + Y3*PsubQ3;
var XdotX = X1*X1 + X2*X2 + X3*X3;
var YdotY = Y1*Y1 + Y2*Y2 + Y3*Y3;
var XdotY = X1*Y1 + X2*Y2 + X3*Y3;
var k = (XdotQsubP * YdotY / XdotX + XdotY * YdotPsubQ) / (YdotY - XdotY * XdotY);
return Vector.create([P[0] + k*X1, P[1] + k*X2, P[2] + k*X3]);
},
// Returns the point on the line that is closest to the given point or line/line segment
pointClosestTo: function(obj) {
if (obj.start && obj.end) {
// obj is a line segment
var P = obj.pointClosestTo(this);
return (P === null) ? null : this.pointClosestTo(P);
} else if (obj.direction) {
// obj is a line
if (this.intersects(obj)) { return this.intersectionWith(obj); }
if (this.isParallelTo(obj)) { return null; }
var D = this.direction.elements, E = obj.direction.elements;
var D1 = D[0], D2 = D[1], D3 = D[2], E1 = E[0], E2 = E[1], E3 = E[2];
// Create plane containing obj and the shared normal and intersect this with it
// Thank you: http://www.cgafaq.info/wiki/Line-line_distance
var x = (D3 * E1 - D1 * E3), y = (D1 * E2 - D2 * E1), z = (D2 * E3 - D3 * E2);
var N = [x * E3 - y * E2, y * E1 - z * E3, z * E2 - x * E1];
var P = Plane.create(obj.anchor, N);
return P.intersectionWith(this);
} else {
// obj is a point
var P = obj.elements || obj;
if (this.contains(P)) { return Vector.create(P); }
var A = this.anchor.elements, D = this.direction.elements;
var D1 = D[0], D2 = D[1], D3 = D[2], A1 = A[0], A2 = A[1], A3 = A[2];
var x = D1 * (P[1]-A2) - D2 * (P[0]-A1), y = D2 * ((P[2] || 0) - A3) - D3 * (P[1]-A2),
z = D3 * (P[0]-A1) - D1 * ((P[2] || 0) - A3);
var V = Vector.create([D2 * x - D3 * z, D3 * y - D1 * x, D1 * z - D2 * y]);
var k = this.distanceFrom(P) / V.modulus();
return Vector.create([
P[0] + V.elements[0] * k,
P[1] + V.elements[1] * k,
(P[2] || 0) + V.elements[2] * k
]);
}
},
// Returns a copy of the line rotated by t radians about the given line. Works by
// finding the argument's closest point to this line's anchor point (call this C) and
// rotating the anchor about C. Also rotates the line's direction about the argument's.
// Be careful with this - the rotation axis' direction affects the outcome!
rotate: function(t, line) {
// If we're working in 2D
if (typeof(line.direction) == 'undefined') { line = Line.create(line.to3D(), Vector.k); }
var R = Matrix.Rotation(t, line.direction).elements;
var C = line.pointClosestTo(this.anchor).elements;
var A = this.anchor.elements, D = this.direction.elements;
var C1 = C[0], C2 = C[1], C3 = C[2], A1 = A[0], A2 = A[1], A3 = A[2];
var x = A1 - C1, y = A2 - C2, z = A3 - C3;
return Line.create([
C1 + R[0][0] * x + R[0][1] * y + R[0][2] * z,
C2 + R[1][0] * x + R[1][1] * y + R[1][2] * z,
C3 + R[2][0] * x + R[2][1] * y + R[2][2] * z
], [
R[0][0] * D[0] + R[0][1] * D[1] + R[0][2] * D[2],
R[1][0] * D[0] + R[1][1] * D[1] + R[1][2] * D[2],
R[2][0] * D[0] + R[2][1] * D[1] + R[2][2] * D[2]
]);
},
// Returns a copy of the line with its direction vector reversed.
// Useful when using lines for rotations.
reverse: function() {
return Line.create(this.anchor, this.direction.x(-1));
},
// Returns the line's reflection in the given point or line
reflectionIn: function(obj) {
if (obj.normal) {
// obj is a plane
var A = this.anchor.elements, D = this.direction.elements;
var A1 = A[0], A2 = A[1], A3 = A[2], D1 = D[0], D2 = D[1], D3 = D[2];
var newA = this.anchor.reflectionIn(obj).elements;
// Add the line's direction vector to its anchor, then mirror that in the plane
var AD1 = A1 + D1, AD2 = A2 + D2, AD3 = A3 + D3;
var Q = obj.pointClosestTo([AD1, AD2, AD3]).elements;
var newD = [Q[0] + (Q[0] - AD1) - newA[0], Q[1] + (Q[1] - AD2) - newA[1], Q[2] + (Q[2] - AD3) - newA[2]];
return Line.create(newA, newD);
} else if (obj.direction) {
// obj is a line - reflection obtained by rotating PI radians about obj
return this.rotate(Math.PI, obj);
} else {
// obj is a point - just reflect the line's anchor in it
var P = obj.elements || obj;
return Line.create(this.anchor.reflectionIn([P[0], P[1], (P[2] || 0)]), this.direction);
}
},
// Set the line's anchor point and direction.
setVectors: function(anchor, direction) {
// Need to do this so that line's properties are not
// references to the arguments passed in
anchor = Vector.create(anchor);
direction = Vector.create(direction);
if (anchor.elements.length == 2) {anchor.elements.push(0); }
if (direction.elements.length == 2) { direction.elements.push(0); }
if (anchor.elements.length > 3 || direction.elements.length > 3) { return null; }
var mod = direction.modulus();
if (mod === 0) { return null; }
this.anchor = anchor;
this.direction = Vector.create([
direction.elements[0] / mod,
direction.elements[1] / mod,
direction.elements[2] / mod
]);
return this;
}
};
// Constructor function
Line.create = function(anchor, direction) {
var L = new Line();
return L.setVectors(anchor, direction);
};
// Axes
Line.X = Line.create(Vector.Zero(3), Vector.i);
Line.Y = Line.create(Vector.Zero(3), Vector.j);
Line.Z = Line.create(Vector.Zero(3), Vector.k);
module.exports = Line;
},{"./matrix":25,"./plane":26,"./sylvester":27,"./vector":28}],24:[function(require,module,exports){
// Copyright (c) 2011, Chris Umbel, James Coglan
// Line.Segment class - depends on Line and its dependencies.
var Line = require('./line');
var Vector = require('./vector');
Line.Segment = function() {};
Line.Segment.prototype = {
// Returns true iff the line segment is equal to the argument
eql: function(segment) {
return (this.start.eql(segment.start) && this.end.eql(segment.end)) ||
(this.start.eql(segment.end) && this.end.eql(segment.start));
},
// Returns a copy of the line segment
dup: function() {
return Line.Segment.create(this.start, this.end);
},
// Returns the length of the line segment
length: function() {
var A = this.start.elements, B = this.end.elements;
var C1 = B[0] - A[0], C2 = B[1] - A[1], C3 = B[2] - A[2];
return Math.sqrt(C1*C1 + C2*C2 + C3*C3);
},
// Returns the line segment as a vector equal to its
// end point relative to its endpoint
toVector: function() {
var A = this.start.elements, B = this.end.elements;
return Vector.create([B[0] - A[0], B[1] - A[1], B[2] - A[2]]);
},
// Returns the segment's midpoint as a vector
midpoint: function() {
var A = this.start.elements, B = this.end.elements;
return Vector.create([(B[0] + A[0])/2, (B[1] + A[1])/2, (B[2] + A[2])/2]);
},
// Returns the plane that bisects the segment
bisectingPlane: function() {
return Plane.create(this.midpoint(), this.toVector());
},
// Returns the result of translating the line by the given vector/array
translate: function(vector) {
var V = vector.elements || vector;
var S = this.start.elements, E = this.end.elements;
return Line.Segment.create(
[S[0] + V[0], S[1] + V[1], S[2] + (V[2] || 0)],
[E[0] + V[0], E[1] + V[1], E[2] + (V[2] || 0)]
);
},
// Returns true iff the line segment is parallel to the argument. It simply forwards
// the method call onto its line property.
isParallelTo: function(obj) {
return this.line.isParallelTo(obj);
},
// Returns the distance between the argument and the line segment's closest point to the argument
distanceFrom: function(obj) {
var P = this.pointClosestTo(obj);
return (P === null) ? null : P.distanceFrom(obj);
},
// Returns true iff the given point lies on the segment
contains: function(obj) {
if (obj.start && obj.end) { return this.contains(obj.start) && this.contains(obj.end); }
var P = (obj.elements || obj).slice();
if (P.length == 2) { P.push(0); }
if (this.start.eql(P)) { return true; }
var S = this.start.elements;
var V = Vector.create([S[0] - P[0], S[1] - P[1], S[2] - (P[2] || 0)]);
var vect = this.toVector();
return V.isAntiparallelTo(vect) && V.modulus() <= vect.modulus();
},
// Returns true iff the line segment intersects the argument
intersects: function(obj) {
return (this.intersectionWith(obj) !== null);
},
// Returns the unique point of intersection with the argument
intersectionWith: function(obj) {
if (!this.line.intersects(obj)) { return null; }
var P = this.line.intersectionWith(obj);
return (this.contains(P) ? P : null);
},
// Returns the point on the line segment closest to the given object
pointClosestTo: function(obj) {
if (obj.normal) {
// obj is a plane
var V = this.line.intersectionWith(obj);
if (V === null) { return null; }
return this.pointClosestTo(V);
} else {
// obj is a line (segment) or point
var P = this.line.pointClosestTo(obj);
if (P === null) { return null; }
if (this.contains(P)) { return P; }
return (this.line.positionOf(P) < 0 ? this.start : this.end).dup();
}
},
// Set the start and end-points of the segment
setPoints: function(startPoint, endPoint) {
startPoint = Vector.create(startPoint).to3D();
endPoint = Vector.create(endPoint).to3D();
if (startPoint === null || endPoint === null) { return null; }
this.line = Line.create(startPoint, endPoint.subtract(startPoint));
this.start = startPoint;
this.end = endPoint;
return this;
}
};
// Constructor function
Line.Segment.create = function(v1, v2) {
var S = new Line.Segment();
return S.setPoints(v1, v2);
};
module.exports = Line.Segment;
},{"./line":23,"./vector":28}],25:[function(require,module,exports){
// Copyright (c) 2011, Chris Umbel, James Coglan
// Matrix class - depends on Vector.
var fs = require('fs');
var Sylvester = require('./sylvester');
var Vector = require('./vector');
// augment a matrix M with identity rows/cols
function identSize(M, m, n, k) {
var e = M.elements;
var i = k - 1;
while(i--) {
var row = [];
for(var j = 0; j < n; j++)
row.push(j == i ? 1 : 0);
e.unshift(row);
}
for(var i = k - 1; i < m; i++) {
while(e[i].length < n)
e[i].unshift(0);
}
return $M(e);
}
function pca(X) {
var Sigma = X.transpose().x(X).x(1 / X.rows());
var svd = Sigma.svd();
return {U: svd.U, S: svd.S};
}
// singular value decomposition in pure javascript
function svdJs() {
var A = this;
var V = Matrix.I(A.rows());
var S = A.transpose();
var U = Matrix.I(A.cols());
var err = Number.MAX_VALUE;
var i = 0;
var maxLoop = 100;
while(err > 2.2737e-13 && i < maxLoop) {
var qr = S.transpose().qrJs();
S = qr.R;
V = V.x(qr.Q);
qr = S.transpose().qrJs();
U = U.x(qr.Q);
S = qr.R;
var e = S.triu(1).unroll().norm();
var f = S.diagonal().norm();
if(f == 0)
f = 1;
err = e / f;
i++;
}
var ss = S.diagonal();
var s = [];
for(var i = 1; i <= ss.cols(); i++) {
var ssn = ss.e(i);
s.push(Math.abs(ssn));
if(ssn < 0) {
for(var j = 0; j < U.rows(); j++) {
V.elements[j][i - 1] = -(V.elements[j][i - 1]);
}
}
}
return {U: U, S: $V(s).toDiagonalMatrix(), V: V};
}
// singular value decomposition using LAPACK
function svdPack() {
var result = lapack.sgesvd('A', 'A', this.elements);
return {
U: $M(result.U),
S: $M(result.S).column(1).toDiagonalMatrix(),
V: $M(result.VT).transpose()
};
}
// QR decomposition in pure javascript
function qrJs() {
var m = this.rows();
var n = this.cols();
var Q = Matrix.I(m);
var A = this;
for(var k = 1; k < Math.min(m, n); k++) {
var ak = A.slice(k, 0, k, k).col(1);
var oneZero = [1];
while(oneZero.length <= m - k)
oneZero.push(0);
oneZero = $V(oneZero);
var vk = ak.add(oneZero.x(ak.norm() * Math.sign(ak.e(1))));
var Vk = $M(vk);
var Hk = Matrix.I(m - k + 1).subtract(Vk.x(2).x(Vk.transpose()).div(Vk.transpose().x(Vk).e(1, 1)));
var Qk = identSize(Hk, m, n, k);
A = Qk.x(A);
// slow way to compute Q
Q = Q.x(Qk);
}
return {Q: Q, R: A};
}
// QR decomposition using LAPACK
function qrPack() {
var qr = lapack.qr(this.elements);
return {
Q: $M(qr.Q),
R: $M(qr.R)
};
}
function Matrix() {}
Matrix.prototype = {
// solve a system of linear equations (work in progress)
solve: function(b) {
var lu = this.lu();
b = lu.P.x(b);
var y = lu.L.forwardSubstitute(b);
var x = lu.U.backSubstitute(y);
return lu.P.x(x);
//return this.inv().x(b);
},
// project a matrix onto a lower dim
pcaProject: function(k, U) {
var U = U || pca(this).U;
var Ureduce= U.slice(1, U.rows(), 1, k);
return {Z: this.x(Ureduce), U: U};
},
// recover a matrix to a higher dimension
pcaRecover: function(U) {
var k = this.cols();
var Ureduce = U.slice(1, U.rows(), 1, k);
return this.x(Ureduce.transpose());
},
// grab the upper triangular part of the matrix
triu: function(k) {
if(!k)
k = 0;
return this.map(function(x, i, j) {
return j - i >= k ? x : 0;
});
},
// unroll a matrix into a vector
unroll: function() {
var v = [];
for(var i = 1; i <= this.cols(); i++) {
for(var j = 1; j <= this.rows(); j++) {
v.push(this.e(j, i));
}
}
return $V(v);
},
// return a sub-block of the matrix
slice: function(startRow, endRow, startCol, endCol) {
var x = [];
if(endRow == 0)
endRow = this.rows();
if(endCol == 0)
endCol = this.cols();
for(i = startRow; i <= endRow; i++) {
var row = [];
for(j = startCol; j <= endCol; j++) {
row.push(this.e(i, j));
}
x.push(row);
}
return $M(x);
},
// Returns element (i,j) of the matrix
e: function(i,j) {
if (i < 1 || i > this.elements.length || j < 1 || j > this.elements[0].length) { return null; }
return this.elements[i - 1][j - 1];
},
// Returns row k of the matrix as a vector
row: function(i) {
if (i > this.elements.length) { return null; }
return $V(this.elements[i - 1]);
},
// Returns column k of the matrix as a vector
col: function(j) {
if (j > this.elements[0].length) { return null; }
var col = [], n = this.elements.length;
for (var i = 0; i < n; i++) { col.push(this.elements[i][j - 1]); }
return $V(col);
},
// Returns the number of rows/columns the matrix has
dimensions: function() {
return {rows: this.elements.length, cols: this.elements[0].length};
},
// Returns the number of rows in the matrix
rows: function() {
return this.elements.length;
},
// Returns the number of columns in the matrix
cols: function() {
return this.elements[0].length;
},
approxEql: function(matrix) {
return this.eql(matrix, Sylvester.approxPrecision);
},
// Returns true iff the matrix is equal to the argument. You can supply
// a vector as the argument, in which case the receiver must be a
// one-column matrix equal to the vector.
eql: function(matrix, precision) {
var M = matrix.elements || matrix;
if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
if (this.elements.length != M.length ||
this.elements[0].length != M[0].length) { return false; }
var i = this.elements.length, nj = this.elements[0].length, j;
while (i--) { j = nj;
while (j--) {
if (Math.abs(this.elements[i][j] - M[i][j]) > (precision || Sylvester.precision)) { return false; }
}
}
return true;
},
// Returns a copy of the matrix
dup: function() {
return Matrix.create(this.elements);
},
// Maps the matrix to another matrix (of the same dimensions) according to the given function
map: function(fn) {
var els = [], i = this.elements.length, nj = this.elements[0].length, j;
while (i--) { j = nj;
els[i] = [];
while (j--) {
els[i][j] = fn(this.elements[i][j], i + 1, j + 1);
}
}
return Matrix.create(els);
},
// Returns true iff the argument has the same dimensions as the matrix
isSameSizeAs: function(matrix) {
var M = matrix.elements || matrix;
if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
return (this.elements.length == M.length &&
this.elements[0].length == M[0].length);
},
// Returns the result of adding the argument to the matrix
add: function(matrix) {
if(typeof(matrix) == 'number') {
return this.map(function(x, i, j) { return x + matrix});
} else {
var M = matrix.elements || matrix;
if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
if (!this.isSameSizeAs(M)) { return null; }
return this.map(function(x, i, j) { return x + M[i - 1][j - 1]; });
}
},
// Returns the result of subtracting the argument from the matrix
subtract: function(matrix) {
if(typeof(matrix) == 'number') {
return this.map(function(x, i, j) { return x - matrix});
} else {
var M = matrix.elements || matrix;
if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
if (!this.isSameSizeAs(M)) { return null; }
return this.map(function(x, i, j) { return x - M[i - 1][j - 1]; });
}
},
// Returns true iff the matrix can multiply the argument from the left
canMultiplyFromLeft: function(matrix) {
var M = matrix.elements || matrix;
if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
// this.columns should equal matrix.rows
return (this.elements[0].length == M.length);
},
// Returns the result of a multiplication-style operation the matrix from the right by the argument.
// If the argument is a scalar then just operate on all the elements. If the argument is
// a vector, a vector is returned, which saves you having to remember calling
// col(1) on the result.
mulOp: function(matrix, op) {
if (!matrix.elements) {
return this.map(function(x) { return op(x, matrix); });
}
var returnVector = matrix.modulus ? true : false;
var M = matrix.elements || matrix;
if (typeof(M[0][0]) == 'undefined')
M = Matrix.create(M).elements;
if (!this.canMultiplyFromLeft(M))
return null;
var e = this.elements, rowThis, rowElem, elements = [],
sum, m = e.length, n = M[0].length, o = e[0].length, i = m, j, k;
while (i--) {
rowElem = [];
rowThis = e[i];
j = n;
while (j--) {
sum = 0;
k = o;
while (k--) {
sum += op(rowThis[k], M[k][j]);
}
rowElem[j] = sum;
}
elements[i] = rowElem;
}
var M = Matrix.create(elements);
return returnVector ? M.col(1) : M;
},
// Returns the result of dividing the matrix from the right by the argument.
// If the argument is a scalar then just divide all the elements. If the argument is
// a vector, a vector is returned, which saves you having to remember calling
// col(1) on the result.
div: function(matrix) {
return this.mulOp(matrix, function(x, y) { return x / y});
},
// Returns the result of multiplying the matrix from the right by the argument.
// If the argument is a scalar then just multiply all the elements. If the argument is
// a vector, a vector is returned, which saves you having to remember calling
// col(1) on the result.
multiply: function(matrix) {
return this.mulOp(matrix, function(x, y) { return x * y});
},
x: function(matrix) { return this.multiply(matrix); },
elementMultiply: function(v) {
return this.map(function(k, i, j) {
return v.e(i, j) * k;
});
},
// sum all elements in the matrix
sum: function() {
var sum = 0;
this.map(function(x) { sum += x;});
return sum;
},
// Returns a Vector of each colum averaged.
mean: function() {
var dim = this.dimensions();
var r = [];
for (var i = 1; i <= dim.cols; i++) {
r.push(this.col(i).sum() / dim.rows);
}
return $V(r);
},
column: function(n) {
return this.col(n);
},
// element-wise log
log: function() {
return this.map(function(x) { return Math.log(x); });
},
// Returns a submatrix taken from the matrix
// Argument order is: start row, start col, nrows, ncols
// Element selection wraps if the required index is outside the matrix's bounds, so you could
// use this to perform row/column cycling or copy-augmenting.
minor: function(a, b, c, d) {
var elements = [], ni = c, i, nj, j;
var rows = this.elements.length, cols = this.elements[0].length;
while (ni--) {
i = c - ni - 1;
elements[i] = [];
nj = d;
while (nj--) {
j = d - nj - 1;
elements[i][j] = this.elements[(a + i - 1) % rows][(b + j - 1) % cols];
}
}
return Matrix.create(elements);
},
// Returns the transpose of the matrix
transpose: function() {
var rows = this.elements.length, i, cols = this.elements[0].length, j;
var elements = [], i = cols;
while (i--) {
j = rows;
elements[i] = [];
while (j--) {
elements[i][j] = this.elements[j][i];
}
}
return Matrix.create(elements);
},
// Returns true iff the matrix is square
isSquare: function() {
return (this.elements.length == this.elements[0].length);
},
// Returns the (absolute) largest element of the matrix
max: function() {
var m = 0, i = this.elements.length, nj = this.elements[0].length, j;
while (i--) {
j = nj;
while (j--) {
if (Math.abs(this.elements[i][j]) > Math.abs(m)) { m = this.elements[i][j]; }
}
}
return m;
},
// Returns the indeces of the first match found by reading row-by-row from left to right
indexOf: function(x) {
var index = null, ni = this.elements.length, i, nj = this.elements[0].length, j;
for (i = 0; i < ni; i++) {
for (j = 0; j < nj; j++) {
if (this.elements[i][j] == x) { return {i: i + 1, j: j + 1}; }
}
}
return null;
},
// If the matrix is square, returns the diagonal elements as a vector.
// Otherwise, returns null.
diagonal: function() {
if (!this.isSquare) { return null; }
var els = [], n = this.elements.length;
for (var i = 0; i < n; i++) {
els.push(this.elements[i][i]);
}
return $V(els);
},
// Make the matrix upper (right) triangular by Gaussian elimination.
// This method only adds multiples of rows to other rows. No rows are
// scaled up or switched, and the determinant is preserved.
toRightTriangular: function() {
var M = this.dup(), els;
var n = this.elements.length, i, j, np = this.elements[0].length, p;
for (i = 0; i < n; i++) {
if (M.elements[i][i] == 0) {
for (j = i + 1; j < n; j++) {
if (M.elements[j][i] != 0) {
els = [];
for (p = 0; p < np; p++) { els.push(M.elements[i][p] + M.elements[j][p]); }
M.elements[i] = els;
break;
}
}
}
if (M.elements[i][i] != 0) {
for (j = i + 1; j < n; j++) {
var multiplier = M.elements[j][i] / M.elements[i][i];
els = [];
for (p = 0; p < np; p++) {
// Elements with column numbers up to an including the number
// of the row that we're subtracting can safely be set straight to
// zero, since that's the point of this routine and it avoids having
// to loop over and correct rounding errors later
els.push(p <= i ? 0 : M.elements[j][p] - M.elements[i][p] * multiplier);
}
M.elements[j] = els;
}
}
}
return M;
},
toUpperTriangular: function() { return this.toRightTriangular(); },
// Returns the determinant for square matrices
determinant: function() {
if (!this.isSquare()) { return null; }
if (this.cols == 1 && this.rows == 1) { return this.row(1); }
if (this.cols == 0 && this.rows == 0) { return 1; }
var M = this.toRightTriangular();
var det = M.elements[0][0], n = M.elements.length;
for (var i = 1; i < n; i++) {
det = det * M.elements[i][i];
}
return det;
},
det: function() { return this.determinant(); },
// Returns true iff the matrix is singular
isSingular: function() {
return (this.isSquare() && this.determinant() === 0);
},
// Returns the trace for square matrices
trace: function() {
if (!this.isSquare()) { return null; }
var tr = this.elements[0][0], n = this.elements.length;
for (var i = 1; i < n; i++) {
tr += this.elements[i][i];
}
return tr;
},
tr: function() { return this.trace(); },
// Returns the rank of the matrix
rank: function() {
var M = this.toRightTriangular(), rank = 0;
var i = this.elements.length, nj = this.elements[0].length, j;
while (i--) {
j = nj;
while (j--) {
if (Math.abs(M.elements[i][j]) > Sylvester.precision) { rank++; break; }
}
}
return rank;
},
rk: function() { return this.rank(); },
// Returns the result of attaching the given argument to the right-hand side of the matrix
augment: function(matrix) {
var M = matrix.elements || matrix;
if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
var T = this.dup(), cols = T.elements[0].length;
var i = T.elements.length, nj = M[0].length, j;
if (i != M.length) { return null; }
while (i--) {
j = nj;
while (j--) {
T.elements[i][cols + j] = M[i][j];
}
}
return T;
},
// Returns the inverse (if one exists) using Gauss-Jordan
inverse: function() {
if (!this.isSquare() || this.isSingular()) { return null; }
var n = this.elements.length, i = n, j;
var M = this.augment(Matrix.I(n)).toRightTriangular();
var np = M.elements[0].length, p, els, divisor;
var inverse_elements = [], new_element;
// Matrix is non-singular so there will be no zeros on the diagonal
// Cycle through rows from last to first
while (i--) {
// First, normalise diagonal elements to 1
els = [];
inverse_elements[i] = [];
divisor = M.elements[i][i];
for (p = 0; p < np; p++) {
new_element = M.elements[i][p] / divisor;
els.push(new_element);
// Shuffle off the current row of the right hand side into the results
// array as it will not be modified by later runs through this loop
if (p >= n) { inverse_elements[i].push(new_element); }
}
M.elements[i] = els;
// Then, subtract this row from those above it to
// give the identity matrix on the left hand side
j = i;
while (j--) {
els = [];
for (p = 0; p < np; p++) {
els.push(M.elements[j][p] - M.elements[i][p] * M.elements[j][i]);
}
M.elements[j] = els;
}
}
return Matrix.create(inverse_elements);
},
inv: function() { return this.inverse(); },
// Returns the result of rounding all the elements
round: function() {
return this.map(function(x) { return Math.round(x); });
},
// Returns a copy of the matrix with elements set to the given value if they
// differ from it by less than Sylvester.precision
snapTo: function(x) {
return this.map(function(p) {
return (Math.abs(p - x) <= Sylvester.precision) ? x : p;
});
},
// Returns a string representation of the matrix
inspect: function() {
var matrix_rows = [];
var n = this.elements.length;
for (var i = 0; i < n; i++) {
matrix_rows.push($V(this.elements[i]).inspect());
}
return matrix_rows.join('\n');
},
// Returns a array representation of the matrix
toArray: function() {
var matrix_rows = [];
var n = this.elements.length;
for (var i = 0; i < n; i++) {
matrix_rows.push(this.elements[i]);
}
return matrix_rows;
},
// Set the matrix's elements from an array. If the argument passed
// is a vector, the resulting matrix will be a single column.
setElements: function(els) {
var i, j, elements = els.elements || els;
if (typeof(elements[0][0]) != 'undefined') {
i = elements.length;
this.elements = [];
while (i--) {
j = elements[i].length;
this.elements[i] = [];
while (j--) {
this.elements[i][j] = elements[i][j];
}
}
return this;
}
var n = elements.length;
this.elements = [];
for (i = 0; i < n; i++) {
this.elements.push([elements[i]]);
}
return this;
},
// return the indexes of the columns with the largest value
// for each row
maxColumnIndexes: function() {
var maxes = [];
for(var i = 1; i <= this.rows(); i++) {
var max = null;
var maxIndex = -1;
for(var j = 1; j <= this.cols(); j++) {
if(max === null || this.e(i, j) > max) {
max = this.e(i, j);
maxIndex = j;
}
}
maxes.push(maxIndex);
}
return $V(maxes);
},
// return the largest values in each row
maxColumns: function() {
var maxes = [];
for(var i = 1; i <= this.rows(); i++) {
var max = null;
for(var j = 1; j <= this.cols(); j++) {
if(max === null || this.e(i, j) > max) {
max = this.e(i, j);
}
}
maxes.push(max);
}
return $V(maxes);
},
// return the indexes of the columns with the smallest values
// for each row
minColumnIndexes: function() {
var mins = [];
for(var i = 1; i <= this.rows(); i++) {
var min = null;
var minIndex = -1;
for(var j = 1; j <= this.cols(); j++) {
if(min === null || this.e(i, j) < min) {
min = this.e(i, j);
minIndex = j;
}
}
mins.push(minIndex);
}
return $V(mins);
},
// return the smallest values in each row
minColumns: function() {
var mins = [];
for(var i = 1; i <= this.rows(); i++) {
var min = null;
for(var j = 1; j <= this.cols(); j++) {
if(min === null || this.e(i, j) < min) {
min = this.e(i, j);
}
}
mins.push(min);
}
return $V(mins);
},
// perorm a partial pivot on the matrix. essentially move the largest
// row below-or-including the pivot and replace the pivot's row with it.
// a pivot matrix is returned so multiplication can perform the transform.
partialPivot: function(k, j, P, A, L) {
var maxIndex = 0;
var maxValue = 0;
for(var i = k; i <= A.rows(); i++) {
if(Math.abs(A.e(i, j)) > maxValue) {
maxValue = Math.abs(A.e(k, j));
maxIndex = i;
}
}
if(maxIndex != k) {
var tmp = A.elements[k - 1];
A.elements[k - 1] = A.elements[maxIndex - 1];
A.elements[maxIndex - 1] = tmp;
P.elements[k - 1][k - 1] = 0;
P.elements[k - 1][maxIndex - 1] = 1;
P.elements[maxIndex - 1][maxIndex - 1] = 0;
P.elements[maxIndex - 1][k - 1] = 1;
}
return P;
},
// solve lower-triangular matrix * x = b via forward substitution
forwardSubstitute: function(b) {
var xa = [];
for(var i = 1; i <= this.rows(); i++) {
var w = 0;
for(var j = 1; j < i; j++) {
w += this.e(i, j) * xa[j - 1];
}
xa.push((b.e(i) - w) / this.e(i, i));
}
return $V(xa);
},
// solve an upper-triangular matrix * x = b via back substitution
backSubstitute: function(b) {
var xa = [];
for(var i = this.rows(); i > 0; i--) {
var w = 0;
for(var j = this.cols(); j > i; j--) {
w += this.e(i, j) * xa[this.rows() - j];
}
xa.push((b.e(i) - w) / this.e(i, i));
}
return $V(xa.reverse());
},
luPack: luPack,
luJs: luJs,
svdJs: svdJs,
svdPack: svdPack,
qrJs: qrJs,
qrPack: qrPack
};
// LU factorization from LAPACK
function luPack() {
var lu = lapack.lu(this.elements);
return {
L: $M(lu.L),
U: $M(lu.U),
P: $M(lu.P)
// don't pass back IPIV
};
}
var tolerance = 1.4901e-08;
// pure Javascript LU factorization
function luJs() {
var A = this.dup();
var L = Matrix.I(A.rows());
var P = Matrix.I(A.rows());
var U = Matrix.Zeros(A.rows(), A.cols());
var p = 1;
for(var k = 1; k <= Math.min(A.cols(), A.rows()); k++) {
P = A.partialPivot(k, p, P, A, L);
for(var i = k + 1; i <= A.rows(); i++) {
var l = A.e(i, p) / A.e(k, p);
L.elements[i - 1][k - 1] = l;
for(var j = k + 1 ; j <= A.cols(); j++) {
A.elements[i - 1][j - 1] -= A.e(k, j) * l;
}
}
for(var j = k; j <= A.cols(); j++) {
U.elements[k - 1][j - 1] = A.e(k, j);
}
if(p < A.cols())
p++;
}
return {L: L, U: U, P: P};
}
function getLapack() {
try {
return require('lapack');
} catch(e) {}
}
var lapack;
// if node-lapack is installed use the fast, native fortran routines
if(lapack = getLapack()) {
Matrix.prototype.svd = svdPack;
Matrix.prototype.qr = qrPack;
Matrix.prototype.lu = luPack;
} else {
// otherwise use the slower pure Javascript versions
Matrix.prototype.svd = svdJs;
Matrix.prototype.qr = qrJs;
Matrix.prototype.lu = luJs;
}
// Constructor function
Matrix.create = function(aElements, ignoreLapack) {
var M = new Matrix().setElements(aElements);
return M;
};
// Identity matrix of size n
Matrix.I = function(n) {
var els = [], i = n, j;
while (i--) {
j = n;
els[i] = [];
while (j--) {
els[i][j] = (i == j) ? 1 : 0;
}
}
return Matrix.create(els);
};
Matrix.loadFile = function(file) {
var contents = fs.readFileSync(file, 'utf-8');
var matrix = [];
var rowArray = contents.split('\n');
for (var i = 0; i < rowArray.length; i++) {
var d = rowArray[i].split(',');
if (d.length > 1) {
matrix.push(d);
}
}
var M = new Matrix();
return M.setElements(matrix);
};
// Diagonal matrix - all off-diagonal elements are zero
Matrix.Diagonal = function(elements) {
var i = elements.length;
var M = Matrix.I(i);
while (i--) {
M.elements[i][i] = elements[i];
}
return M;
};
// Rotation matrix about some axis. If no axis is
// supplied, assume we're after a 2D transform
Matrix.Rotation = function(theta, a) {
if (!a) {
return Matrix.create([
[Math.cos(theta), -Math.sin(theta)],
[Math.sin(theta), Math.cos(theta)]
]);
}
var axis = a.dup();
if (axis.elements.length != 3) { return null; }
var mod = axis.modulus();
var x = axis.elements[0] / mod, y = axis.elements[1] / mod, z = axis.elements[2] / mod;
var s = Math.sin(theta), c = Math.cos(theta), t = 1 - c;
// Formula derived here: http://www.gamedev.net/reference/articles/article1199.asp
// That proof rotates the co-ordinate system so theta
// becomes -theta and sin becomes -sin here.
return Matrix.create([
[t * x * x + c, t * x * y - s * z, t * x * z + s * y],
[t * x * y + s * z, t * y * y + c, t * y * z - s * x],
[t * x * z - s * y, t * y * z + s * x, t * z * z + c]
]);
};
// Special case rotations
Matrix.RotationX = function(t) {
var c = Math.cos(t), s = Math.sin(t);
return Matrix.create([
[1, 0, 0],
[0, c, -s],
[0, s, c]
]);
};
Matrix.RotationY = function(t) {
var c = Math.cos(t), s = Math.sin(t);
return Matrix.create([
[c, 0, s],
[0, 1, 0],
[-s, 0, c]
]);
};
Matrix.RotationZ = function(t) {
var c = Math.cos(t), s = Math.sin(t);
return Matrix.create([
[c, -s, 0],
[s, c, 0],
[0, 0, 1]
]);
};
// Random matrix of n rows, m columns
Matrix.Random = function(n, m) {
if (arguments.length === 1) m = n;
return Matrix.Zero(n, m).map(
function() { return Math.random(); }
);
};
Matrix.Fill = function(n, m, v) {
if (arguments.length === 2) {
v = m;
m = n;
}
var els = [], i = n, j;
while (i--) {
j = m;
els[i] = [];
while (j--) {
els[i][j] = v;
}
}
return Matrix.create(els);
};
// Matrix filled with zeros
Matrix.Zero = function(n, m) {
return Matrix.Fill(n, m, 0);
};
// Matrix filled with zeros
Matrix.Zeros = function(n, m) {
return Matrix.Zero(n, m);
};
// Matrix filled with ones
Matrix.One = function(n, m) {
return Matrix.Fill(n, m, 1);
};
// Matrix filled with ones
Matrix.Ones = function(n, m) {
return Matrix.One(n, m);
};
module.exports = Matrix;
},{"./sylvester":27,"./vector":28,"fs":3,"lapack":9}],26:[function(require,module,exports){
// Copyright (c) 2011, Chris Umbel, James Coglan
// Plane class - depends on Vector. Some methods require Matrix and Line.
var Vector = require('./vector');
var Matrix = require('./matrix');
var Line = require('./line');
var Sylvester = require('./sylvester');
function Plane() {}
Plane.prototype = {
// Returns true iff the plane occupies the same space as the argument
eql: function(plane) {
return (this.contains(plane.anchor) && this.isParallelTo(plane));
},
// Returns a copy of the plane
dup: function() {
return Plane.create(this.anchor, this.normal);
},
// Returns the result of translating the plane by the given vector
translate: function(vector) {
var V = vector.elements || vector;
return Plane.create([
this.anchor.elements[0] + V[0],
this.anchor.elements[1] + V[1],
this.anchor.elements[2] + (V[2] || 0)
], this.normal);
},
// Returns true iff the plane is parallel to the argument. Will return true
// if the planes are equal, or if you give a line and it lies in the plane.
isParallelTo: function(obj) {
var theta;
if (obj.normal) {
// obj is a plane
theta = this.normal.angleFrom(obj.normal);
return (Math.abs(theta) <= Sylvester.precision || Math.abs(Math.PI - theta) <= Sylvester.precision);
} else if (obj.direction) {
// obj is a line
return this.normal.isPerpendicularTo(obj.direction);
}
return null;
},
// Returns true iff the receiver is perpendicular to the argument
isPerpendicularTo: function(plane) {
var theta = this.normal.angleFrom(plane.normal);
return (Math.abs(Math.PI/2 - theta) <= Sylvester.precision);
},
// Returns the plane's distance from the given object (point, line or plane)
distanceFrom: function(obj) {
if (this.intersects(obj) || this.contains(obj)) { return 0; }
if (obj.anchor) {
// obj is a plane or line
var A = this.anchor.elements, B = obj.anchor.elements, N = this.normal.elements;
return Math.abs((A[0] - B[0]) * N[0] + (A[1] - B[1]) * N[1] + (A[2] - B[2]) * N[2]);
} else {
// obj is a point
var P = obj.elements || obj;
var A = this.anchor.elements, N = this.normal.elements;
return Math.abs((A[0] - P[0]) * N[0] + (A[1] - P[1]) * N[1] + (A[2] - (P[2] || 0)) * N[2]);
}
},
// Returns true iff the plane contains the given point or line
contains: function(obj) {
if (obj.normal) { return null; }
if (obj.direction) {
return (this.contains(obj.anchor) && this.contains(obj.anchor.add(obj.direction)));
} else {
var P = obj.elements || obj;
var A = this.anchor.elements, N = this.normal.elements;
var diff = Math.abs(N[0]*(A[0] - P[0]) + N[1]*(A[1] - P[1]) + N[2]*(A[2] - (P[2] || 0)));
return (diff <= Sylvester.precision);
}
},
// Returns true iff the plane has a unique point/line of intersection with the argument
intersects: function(obj) {
if (typeof(obj.direction) == 'undefined' && typeof(obj.normal) == 'undefined') { return null; }
return !this.isParallelTo(obj);
},
// Returns the unique intersection with the argument, if one exists. The result
// will be a vector if a line is supplied, and a line if a plane is supplied.
intersectionWith: function(obj) {
if (!this.intersects(obj)) { return null; }
if (obj.direction) {
// obj is a line
var A = obj.anchor.elements, D = obj.direction.elements,
P = this.anchor.elements, N = this.normal.elements;
var multiplier = (N[0]*(P[0]-A[0]) + N[1]*(P[1]-A[1]) + N[2]*(P[2]-A[2])) / (N[0]*D[0] + N[1]*D[1] + N[2]*D[2]);
return Vector.create([A[0] + D[0]*multiplier, A[1] + D[1]*multiplier, A[2] + D[2]*multiplier]);
} else if (obj.normal) {
// obj is a plane
var direction = this.normal.cross(obj.normal).toUnitVector();
// To find an anchor point, we find one co-ordinate that has a value
// of zero somewhere on the intersection, and remember which one we picked
var N = this.normal.elements, A = this.anchor.elements,
O = obj.normal.elements, B = obj.anchor.elements;
var solver = Matrix.Zero(2,2), i = 0;
while (solver.isSingular()) {
i++;
solver = Matrix.create([
[ N[i%3], N[(i+1)%3] ],
[ O[i%3], O[(i+1)%3] ]
]);
}
// Then we solve the simultaneous equations in the remaining dimensions
var inverse = solver.inverse().elements;
var x = N[0]*A[0] + N[1]*A[1] + N[2]*A[2];
var y = O[0]*B[0] + O[1]*B[1] + O[2]*B[2];
var intersection = [
inverse[0][0] * x + inverse[0][1] * y,
inverse[1][0] * x + inverse[1][1] * y
];
var anchor = [];
for (var j = 1; j <= 3; j++) {
// This formula picks the right element from intersection by
// cycling depending on which element we set to zero above
anchor.push((i == j) ? 0 : intersection[(j + (5 - i)%3)%3]);
}
return Line.create(anchor, direction);
}
},
// Returns the point in the plane closest to the given point
pointClosestTo: function(point) {
var P = point.elements || point;
var A = this.anchor.elements, N = this.normal.elements;
var dot = (A[0] - P[0]) * N[0] + (A[1] - P[1]) * N[1] + (A[2] - (P[2] || 0)) * N[2];
return Vector.create([P[0] + N[0] * dot, P[1] + N[1] * dot, (P[2] || 0) + N[2] * dot]);
},
// Returns a copy of the plane, rotated by t radians about the given line
// See notes on Line#rotate.
rotate: function(t, line) {
var R = t.determinant ? t.elements : Matrix.Rotation(t, line.direction).elements;
var C = line.pointClosestTo(this.anchor).elements;
var A = this.anchor.elements, N = this.normal.elements;
var C1 = C[0], C2 = C[1], C3 = C[2], A1 = A[0], A2 = A[1], A3 = A[2];
var x = A1 - C1, y = A2 - C2, z = A3 - C3;
return Plane.create([
C1 + R[0][0] * x + R[0][1] * y + R[0][2] * z,
C2 + R[1][0] * x + R[1][1] * y + R[1][2] * z,
C3 + R[2][0] * x + R[2][1] * y + R[2][2] * z
], [
R[0][0] * N[0] + R[0][1] * N[1] + R[0][2] * N[2],
R[1][0] * N[0] + R[1][1] * N[1] + R[1][2] * N[2],
R[2][0] * N[0] + R[2][1] * N[1] + R[2][2] * N[2]
]);
},
// Returns the reflection of the plane in the given point, line or plane.
reflectionIn: function(obj) {
if (obj.normal) {
// obj is a plane
var A = this.anchor.elements, N = this.normal.elements;
var A1 = A[0], A2 = A[1], A3 = A[2], N1 = N[0], N2 = N[1], N3 = N[2];
var newA = this.anchor.reflectionIn(obj).elements;
// Add the plane's normal to its anchor, then mirror that in the other plane
var AN1 = A1 + N1, AN2 = A2 + N2, AN3 = A3 + N3;
var Q = obj.pointClosestTo([AN1, AN2, AN3]).elements;
var newN = [Q[0] + (Q[0] - AN1) - newA[0], Q[1] + (Q[1] - AN2) - newA[1], Q[2] + (Q[2] - AN3) - newA[2]];
return Plane.create(newA, newN);
} else if (obj.direction) {
// obj is a line
return this.rotate(Math.PI, obj);
} else {
// obj is a point
var P = obj.elements || obj;
return Plane.create(this.anchor.reflectionIn([P[0], P[1], (P[2] || 0)]), this.normal);
}
},
// Sets the anchor point and normal to the plane. If three arguments are specified,
// the normal is calculated by assuming the three points should lie in the same plane.
// If only two are sepcified, the second is taken to be the normal. Normal vector is
// normalised before storage.
setVectors: function(anchor, v1, v2) {
anchor = Vector.create(anchor);
anchor = anchor.to3D(); if (anchor === null) { return null; }
v1 = Vector.create(v1);
v1 = v1.to3D(); if (v1 === null) { return null; }
if (typeof(v2) == 'undefined') {
v2 = null;
} else {
v2 = Vector.create(v2);
v2 = v2.to3D(); if (v2 === null) { return null; }
}
var A1 = anchor.elements[0], A2 = anchor.elements[1], A3 = anchor.elements[2];
var v11 = v1.elements[0], v12 = v1.elements[1], v13 = v1.elements[2];
var normal, mod;
if (v2 !== null) {
var v21 = v2.elements[0], v22 = v2.elements[1], v23 = v2.elements[2];
normal = Vector.create([
(v12 - A2) * (v23 - A3) - (v13 - A3) * (v22 - A2),
(v13 - A3) * (v21 - A1) - (v11 - A1) * (v23 - A3),
(v11 - A1) * (v22 - A2) - (v12 - A2) * (v21 - A1)
]);
mod = normal.modulus();
if (mod === 0) { return null; }
normal = Vector.create([normal.elements[0] / mod, normal.elements[1] / mod, normal.elements[2] / mod]);
} else {
mod = Math.sqrt(v11*v11 + v12*v12 + v13*v13);
if (mod === 0) { return null; }
normal = Vector.create([v1.elements[0] / mod, v1.elements[1] / mod, v1.elements[2] / mod]);
}
this.anchor = anchor;
this.normal = normal;
return this;
}
};
// Constructor function
Plane.create = function(anchor, v1, v2) {
var P = new Plane();
return P.setVectors(anchor, v1, v2);
};
// X-Y-Z planes
Plane.XY = Plane.create(Vector.Zero(3), Vector.k);
Plane.YZ = Plane.create(Vector.Zero(3), Vector.i);
Plane.ZX = Plane.create(Vector.Zero(3), Vector.j);
Plane.YX = Plane.XY; Plane.ZY = Plane.YZ; Plane.XZ = Plane.ZX;
// Returns the plane containing the given points (can be arrays as
// well as vectors). If the points are not coplanar, returns null.
Plane.fromPoints = function(points) {
var np = points.length, list = [], i, P, n, N, A, B, C, D, theta, prevN, totalN = Vector.Zero(3);
for (i = 0; i < np; i++) {
P = Vector.create(points[i]).to3D();
if (P === null) { return null; }
list.push(P);
n = list.length;
if (n > 2) {
// Compute plane normal for the latest three points
A = list[n-1].elements; B = list[n-2].elements; C = list[n-3].elements;
N = Vector.create([
(A[1] - B[1]) * (C[2] - B[2]) - (A[2] - B[2]) * (C[1] - B[1]),
(A[2] - B[2]) * (C[0] - B[0]) - (A[0] - B[0]) * (C[2] - B[2]),
(A[0] - B[0]) * (C[1] - B[1]) - (A[1] - B[1]) * (C[0] - B[0])
]).toUnitVector();
if (n > 3) {
// If the latest normal is not (anti)parallel to the previous one, we've strayed off the plane.
// This might be a slightly long-winded way of doing things, but we need the sum of all the normals
// to find which way the plane normal should point so that the points form an anticlockwise list.
theta = N.angleFrom(prevN);
if (theta !== null) {
if (!(Math.abs(theta) <= Sylvester.precision || Math.abs(theta - Math.PI) <= Sylvester.precision)) { return null; }
}
}
totalN = totalN.add(N);
prevN = N;
}
}
// We need to add in the normals at the start and end points, which the above misses out
A = list[1].elements; B = list[0].elements; C = list[n-1].elements; D = list[n-2].elements;
totalN = totalN.add(Vector.create([
(A[1] - B[1]) * (C[2] - B[2]) - (A[2] - B[2]) * (C[1] - B[1]),
(A[2] - B[2]) * (C[0] - B[0]) - (A[0] - B[0]) * (C[2] - B[2]),
(A[0] - B[0]) * (C[1] - B[1]) - (A[1] - B[1]) * (C[0] - B[0])
]).toUnitVector()).add(Vector.create([
(B[1] - C[1]) * (D[2] - C[2]) - (B[2] - C[2]) * (D[1] - C[1]),
(B[2] - C[2]) * (D[0] - C[0]) - (B[0] - C[0]) * (D[2] - C[2]),
(B[0] - C[0]) * (D[1] - C[1]) - (B[1] - C[1]) * (D[0] - C[0])
]).toUnitVector());
return Plane.create(list[0], totalN);
};
module.exports = Plane;
},{"./line":23,"./matrix":25,"./sylvester":27,"./vector":28}],27:[function(require,module,exports){
// Copyright (c) 2011, Chris Umbel, James Coglan
// This file is required in order for any other classes to work. Some Vector methods work with the
// other Sylvester classes and are useless unless they are included. Other classes such as Line and
// Plane will not function at all without Vector being loaded first.
Math.sign = function(x) {
return x < 0 ? -1: 1;
}
var Sylvester = {
precision: 1e-6,
approxPrecision: 1e-5
};
module.exports = Sylvester;
},{}],28:[function(require,module,exports){
// Copyright (c) 2011, Chris Umbel, James Coglan
// This file is required in order for any other classes to work. Some Vector methods work with the
// other Sylvester classes and are useless unless they are included. Other classes such as Line and
// Plane will not function at all without Vector being loaded first.
var Sylvester = require('./sylvester'),
Matrix = require('./matrix');
function Vector() {}
Vector.prototype = {
norm: function() {
var n = this.elements.length;
var sum = 0;
while (n--) {
sum += Math.pow(this.elements[n], 2);
}
return Math.sqrt(sum);
},
// Returns element i of the vector
e: function(i) {
return (i < 1 || i > this.elements.length) ? null : this.elements[i - 1];
},
// Returns the number of rows/columns the vector has
dimensions: function() {
return {rows: 1, cols: this.elements.length};
},
// Returns the number of rows in the vector
rows: function() {
return 1;
},
// Returns the number of columns in the vector
cols: function() {
return this.elements.length;
},
// Returns the modulus ('length') of the vector
modulus: function() {
return Math.sqrt(this.dot(this));
},
// Returns true iff the vector is equal to the argument
eql: function(vector) {
var n = this.elements.length;
var V = vector.elements || vector;
if (n != V.length) { return false; }
while (n--) {
if (Math.abs(this.elements[n] - V[n]) > Sylvester.precision) { return false; }
}
return true;
},
// Returns a copy of the vector
dup: function() {
return Vector.create(this.elements);
},
// Maps the vector to another vector according to the given function
map: function(fn) {
var elements = [];
this.each(function(x, i) {
elements.push(fn(x, i));
});
return Vector.create(elements);
},
// Calls the iterator for each element of the vector in turn
each: function(fn) {
var n = this.elements.length;
for (var i = 0; i < n; i++) {
fn(this.elements[i], i + 1);
}
},
// Returns a new vector created by normalizing the receiver
toUnitVector: function() {
var r = this.modulus();
if (r === 0) { return this.dup(); }
return this.map(function(x) { return x / r; });
},
// Returns the angle between the vector and the argument (also a vector)
angleFrom: function(vector) {
var V = vector.elements || vector;
var n = this.elements.length, k = n, i;
if (n != V.length) { return null; }
var dot = 0, mod1 = 0, mod2 = 0;
// Work things out in parallel to save time
this.each(function(x, i) {
dot += x * V[i - 1];
mod1 += x * x;
mod2 += V[i - 1] * V[i - 1];
});
mod1 = Math.sqrt(mod1); mod2 = Math.sqrt(mod2);
if (mod1 * mod2 === 0) { return null; }
var theta = dot / (mod1 * mod2);
if (theta < -1) { theta = -1; }
if (theta > 1) { theta = 1; }
return Math.acos(theta);
},
// Returns true iff the vector is parallel to the argument
isParallelTo: function(vector) {
var angle = this.angleFrom(vector);
return (angle === null) ? null : (angle <= Sylvester.precision);
},
// Returns true iff the vector is antiparallel to the argument
isAntiparallelTo: function(vector) {
var angle = this.angleFrom(vector);
return (angle === null) ? null : (Math.abs(angle - Math.PI) <= Sylvester.precision);
},
// Returns true iff the vector is perpendicular to the argument
isPerpendicularTo: function(vector) {
var dot = this.dot(vector);
return (dot === null) ? null : (Math.abs(dot) <= Sylvester.precision);
},
// Returns the result of adding the argument to the vector
add: function(value) {
var V = value.elements || value;
if (this.elements.length != V.length)
return this.map(function(v) { return v + value });
else
return this.map(function(x, i) { return x + V[i - 1]; });
},
// Returns the result of subtracting the argument from the vector
subtract: function(v) {
if (typeof(v) == 'number')
return this.map(function(k) { return k - v; });
var V = v.elements || v;
if (this.elements.length != V.length) { return null; }
return this.map(function(x, i) { return x - V[i - 1]; });
},
// Returns the result of multiplying the elements of the vector by the argument
multiply: function(k) {
return this.map(function(x) { return x * k; });
},
elementMultiply: function(v) {
return this.map(function(k, i) {
return v.e(i) * k;
});
},
sum: function() {
var sum = 0;
this.map(function(x) { sum += x;});
return sum;
},
chomp: function(n) {
var elements = [];
for (var i = n; i < this.elements.length; i++) {
elements.push(this.elements[i]);
}
return Vector.create(elements);
},
top: function(n) {
var elements = [];
for (var i = 0; i < n; i++) {
elements.push(this.elements[i]);
}
return Vector.create(elements);
},
augment: function(elements) {
var newElements = this.elements;
for (var i = 0; i < elements.length; i++) {
newElements.push(elements[i]);
}
return Vector.create(newElements);
},
x: function(k) { return this.multiply(k); },
log: function() {
return Vector.log(this);
},
elementDivide: function(vector) {
return this.map(function(v, i) {
return v / vector.e(i);
});
},
product: function() {
var p = 1;
this.map(function(v) {
p *= v;
});
return p;
},
// Returns the scalar product of the vector with the argument
// Both vectors must have equal dimensionality
dot: function(vector) {
var V = vector.elements || vector;
var i, product = 0, n = this.elements.length;
if (n != V.length) { return null; }
while (n--) { product += this.elements[n] * V[n]; }
return product;
},
// Returns the vector product of the vector with the argument
// Both vectors must have dimensionality 3
cross: function(vector) {
var B = vector.elements || vector;
if (this.elements.length != 3 || B.length != 3) { return null; }
var A = this.elements;
return Vector.create([
(A[1] * B[2]) - (A[2] * B[1]),
(A[2] * B[0]) - (A[0] * B[2]),
(A[0] * B[1]) - (A[1] * B[0])
]);
},
// Returns the (absolute) largest element of the vector
max: function() {
var m = 0, i = this.elements.length;
while (i--) {
if (Math.abs(this.elements[i]) > Math.abs(m)) { m = this.elements[i]; }
}
return m;
},
maxIndex: function() {
var m = 0, i = this.elements.length;
var maxIndex = -1;
while (i--) {
if (Math.abs(this.elements[i]) > Math.abs(m)) {
m = this.elements[i];
maxIndex = i + 1;
}
}
return maxIndex;
},
// Returns the index of the first match found
indexOf: function(x) {
var index = null, n = this.elements.length;
for (var i = 0; i < n; i++) {
if (index === null && this.elements[i] == x) {
index = i + 1;
}
}
return index;
},
// Returns a diagonal matrix with the vector's elements as its diagonal elements
toDiagonalMatrix: function() {
return Matrix.Diagonal(this.elements);
},
// Returns the result of rounding the elements of the vector
round: function() {
return this.map(function(x) { return Math.round(x); });
},
// Transpose a Vector, return a 1xn Matrix
transpose: function() {
var rows = this.elements.length;
var elements = [];
for (var i = 0; i < rows; i++) {
elements.push([this.elements[i]]);
}
return Matrix.create(elements);
},
// Returns a copy of the vector with elements set to the given value if they
// differ from it by less than Sylvester.precision
snapTo: function(x) {
return this.map(function(y) {
return (Math.abs(y - x) <= Sylvester.precision) ? x : y;
});
},
// Returns the vector's distance from the argument, when considered as a point in space
distanceFrom: function(obj) {
if (obj.anchor || (obj.start && obj.end)) { return obj.distanceFrom(this); }
var V = obj.elements || obj;
if (V.length != this.elements.length) { return null; }
var sum = 0, part;
this.each(function(x, i) {
part = x - V[i - 1];
sum += part * part;
});
return Math.sqrt(sum);
},
// Returns true if the vector is point on the given line
liesOn: function(line) {
return line.contains(this);
},
// Return true iff the vector is a point in the given plane
liesIn: function(plane) {
return plane.contains(this);
},
// Rotates the vector about the given object. The object should be a
// point if the vector is 2D, and a line if it is 3D. Be careful with line directions!
rotate: function(t, obj) {
var V, R = null, x, y, z;
if (t.determinant) { R = t.elements; }
switch (this.elements.length) {
case 2:
V = obj.elements || obj;
if (V.length != 2) { return null; }
if (!R) { R = Matrix.Rotation(t).elements; }
x = this.elements[0] - V[0];
y = this.elements[1] - V[1];
return Vector.create([
V[0] + R[0][0] * x + R[0][1] * y,
V[1] + R[1][0] * x + R[1][1] * y
]);
break;
case 3:
if (!obj.direction) { return null; }
var C = obj.pointClosestTo(this).elements;
if (!R) { R = Matrix.Rotation(t, obj.direction).elements; }
x = this.elements[0] - C[0];
y = this.elements[1] - C[1];
z = this.elements[2] - C[2];
return Vector.create([
C[0] + R[0][0] * x + R[0][1] * y + R[0][2] * z,
C[1] + R[1][0] * x + R[1][1] * y + R[1][2] * z,
C[2] + R[2][0] * x + R[2][1] * y + R[2][2] * z
]);
break;
default:
return null;
}
},
// Returns the result of reflecting the point in the given point, line or plane
reflectionIn: function(obj) {
if (obj.anchor) {
// obj is a plane or line
var P = this.elements.slice();
var C = obj.pointClosestTo(P).elements;
return Vector.create([C[0] + (C[0] - P[0]), C[1] + (C[1] - P[1]), C[2] + (C[2] - (P[2] || 0))]);
} else {
// obj is a point
var Q = obj.elements || obj;
if (this.elements.length != Q.length) { return null; }
return this.map(function(x, i) { return Q[i - 1] + (Q[i - 1] - x); });
}
},
// Utility to make sure vectors are 3D. If they are 2D, a zero z-component is added
to3D: function() {
var V = this.dup();
switch (V.elements.length) {
case 3: break;
case 2: V.elements.push(0); break;
default: return null;
}
return V;
},
// Returns a string representation of the vector
inspect: function() {
return '[' + this.elements.join(', ') + ']';
},
// Set vector's elements from an array
setElements: function(els) {
this.elements = (els.elements || els).slice();
return this;
}
};
// Constructor function
Vector.create = function(elements) {
var V = new Vector();
return V.setElements(elements);
};
// i, j, k unit vectors
Vector.i = Vector.create([1, 0, 0]);
Vector.j = Vector.create([0, 1, 0]);
Vector.k = Vector.create([0, 0, 1]);
// Random vector of size n
Vector.Random = function(n) {
var elements = [];
while (n--) { elements.push(Math.random()); }
return Vector.create(elements);
};
Vector.Fill = function(n, v) {
var elements = [];
while (n--) { elements.push(v); }
return Vector.create(elements);
};
// Vector filled with zeros
Vector.Zero = function(n) {
return Vector.Fill(n, 0);
};
Vector.One = function(n) {
return Vector.Fill(n, 1);
};
Vector.log = function(v) {
return v.map(function(x) {
return Math.log(x);
});
};
module.exports = Vector;
},{"./matrix":25,"./sylvester":27}]},{},[])
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment