Skip to content

Instantly share code, notes, and snippets.

@dribnet
Forked from ferdasonmez/.block
Last active May 15, 2019 17:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dribnet/8284e82ecefefeb391298356d3ab6732 to your computer and use it in GitHub Desktop.
Save dribnet/8284e82ecefefeb391298356d3ab6732 to your computer and use it in GitHub Desktop.
all possible endings
license: gpl-3.0

(click to reload)

Sketch showing several possible variations of a single output from a generative handwriting model. The model first generates a single handwriting sample, then works backwards to show variants further and further into the past.

Based on my fork of Mike Bostock's branched random walk and hardmaru's RNN Tutorial for Artists.

<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<!-- Note: numjs is not quite in cdnjs: https://github.com/cdnjs/cdnjs/pull/10019 -->
<script language="javascript" type="text/javascript" src="numjs.js"></script>
<script language="javascript" type="text/javascript" src="weights.js"></script>
<script language="javascript" type="text/javascript" src="model.js"></script>
<script>
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height,
length = 300,
tail_every = 20,
color = d3.scaleSequential(d3.interpolateRainbow).domain([0, length])
x0 = 0.1 * width,
y0 = 0.5 * height,
pen_up0 = false,
mainWalk = null;
var is_rendering = false;
var last_render_time = 0;
var cur_index;
var do_abort = false;
render();
var redraw_check_interval = 1000; // one second in milliseconds
var redraw_interval = 30 * 1000;
function check_redraw(elapsed) {
var so_far = d3.now() - last_render_time;
if(so_far > redraw_interval && !is_rendering) {
// console.log("YES: " + so_far);
render();
}
d3.timeout(check_redraw, redraw_check_interval);
}
d3.timeout(check_redraw, redraw_check_interval);
canvas.onclick = click_check;
function click_check() {
if(is_rendering) {
do_abort = true;
context.clearRect(0, 0, width, height);
}
else {
render();
}
}
function render() {
if(is_rendering) {
return;
}
last_render_time = d3.now();
is_rendering = true;
context.clearRect(0, 0, width, height);
d3.timeout(render2, 25);
}
function render2(elapsed) {
if(do_abort) {
do_abort = false;
is_rendering = false;
render();
return;
}
mainWalk = handwritingWalk([[x0, y0, pen_up0, null]], length);
context.clearRect(0, 0, width, height);
context.lineJoin = "round";
context.lineCap = "round";
context.lineWidth = 5;
context.strokeStyle = "black";
context.globalAlpha = 0.7;
renderWalk(mainWalk);
context.globalCompositeOperation = "multiply";
context.lineWidth = 2;
cur_index = mainWalk.length - tail_every;
d3.timeout(render3, 25);
}
function render3(elapsed) {
if(do_abort) {
do_abort = false;
is_rendering = false;
render();
return;
}
var branchHistory = mainWalk.slice(0, cur_index+1);
tail_length = mainWalk.length - cur_index;
tail_chunk = Math.floor(tail_length / 20);
for (var j = 0; j < 1; ++j) {
context.strokeStyle = color(cur_index);
branchCopy = branchHistory.slice();
for (var k = 0, m = 20; k < m; ++k) {
context.globalAlpha = (m - k - 1) / m;
var pieceWalk;
pieceWalk = handwritingWalk(branchCopy, tail_chunk);
var pieceEnd = pieceWalk[pieceWalk.length - 1];
renderWalk(pieceWalk);
branchCopy.push(pieceEnd)
}
context.globalAlpha = 1;
}
cur_index -= tail_every;
if(cur_index <= tail_every) {
is_rendering = false;
}
else {
d3.timeout(render3, 25);
}
}
function renderWalk(walk) {
var i, n = walk.length;
context.beginPath();
context.moveTo(walk[0][0], walk[0][1]);
for (i = 1; i < n; ++i) {
// check for pen_up
if(walk[i-1][2]) {
context.moveTo(walk[i][0], walk[i][1]);
}
else {
context.lineTo(walk[i][0], walk[i][1]);
}
}
context.stroke();
}
// This works similiar to randomWalk.
function handwritingWalk(history, n, temperature) {
var points = new Array(n), i, x, y, pen_up;
var initial_state, rnn_state, temp_state;
if (temperature === undefined) {
temperature = 0.25;
}
// initialize the scale factor for the model. Bigger -> large outputs
Model.set_scale_factor(16.0);
// TODO: this is probably unnecessary
// initialize pen's states to zero.
Model.zero_input(); // the pen's states
points[0] = history[history.length - 1];
[x, y, pen_up, initial_state] = points[0];
temp_state = null;
// plug in history
if(initial_state === null) {
// initialize the rnn's initial states to zero
rnn_state = Model.random_state();
}
else {
rnn_state = Model.copy_state(initial_state)
}
// idea: could init from points only. eg:
// for(i=0; i<history.length; i++) {
// rnn_state = Model.update( /* compute dx, dy, pen here */, rnn_state);
// }
for(i=1; i<n; i++) {
// get the parameters of the probability distribution (pdf) from hidden state
pdf = Model.get_pdf(rnn_state);
// sample the next pen's states from our probability distribution
next_step = Model.sample(pdf, temperature);
// update state
rnn_state = Model.update(next_step, rnn_state);
temp_state = Model.copy_state(rnn_state);
// save path
points[i] = [
x += next_step[0],
y += next_step[1],
next_step[2],
temp_state
];
}
return points;
}
</script>
// handwriting mdn-lstm model ported to JS
if (typeof module != "undefined") {
}
var Model = {};
(function(global) {
"use strict";
// init (import weights from weights.js)
var string_to_uint8array = function(b64encoded) {
var u8 = new Uint8Array(atob(b64encoded).split("").map(function(c) {
return c.charCodeAt(0); }));
return u8;
}
var uintarray_to_string = function(u8) {
var b64encoded = btoa(String.fromCharCode.apply(null, u8));
return b64encoded;
};
function encode_array(raw_array) {
var i;
var N = raw_array.length;
var x = [];
for (i=0;i<N;i++) {
x.push(raw_array[i]+127);
}
var u8 = new Uint8Array(x);
return uintarray_to_string(u8);
}
function decode_string(b64encoded) {
var i;
var raw_array = string_to_uint8array(b64encoded);
var N = raw_array.length;
var x = [];
for (i=0;i<N;i++) {
x.push(raw_array[i]-127);
}
return x;
}
function encode_2d_array(raw_2d_array) {
var i;
var N = raw_2d_array.length;
var x = [];
var temp;
for (i=0;i<N;i++) {
temp = encode_array(raw_2d_array[i]);
x.push(temp);
}
return x;
}
function decode_2d_string(raw_2d_array) {
var i;
var N = raw_2d_array.length;
var x = [];
var temp;
for (i=0;i<N;i++) {
temp = decode_string(raw_2d_array[i]);
x.push(temp);
}
return x;
}
var bdata = JSON.parse(lstm_data);
var raw_output_w = decode_2d_string(bdata[0]);
var raw_output_b = decode_string(bdata[1]);
var raw_LSTM_Wxh = decode_2d_string(bdata[2]);
var raw_LSTM_Whh = decode_2d_string(bdata[3]);
var raw_LSTM_bias = decode_string(bdata[4]);
var scale_output_w = 1.5;
var scale_output_b = 2.5;
var scale_LSTM_Wxh = 2.0;
var scale_LSTM_Whh = 0.8;
var scale_LSTM_bias = 1.5;
var output_w = nj.array(raw_output_w);
var output_b = nj.array(raw_output_b);
var LSTM_Wxh = nj.array(raw_LSTM_Wxh);
var LSTM_Whh = nj.array(raw_LSTM_Whh);
var LSTM_bias = nj.array(raw_LSTM_bias);
output_w = output_w.divide(127);
output_w = output_w.multiply(scale_output_w);
output_b = output_b.divide(127);
output_b = output_b.multiply(scale_output_b);
LSTM_Wxh = LSTM_Wxh.divide(127);
LSTM_Wxh = LSTM_Wxh.multiply(scale_LSTM_Wxh);
LSTM_Whh = LSTM_Whh.divide(127);
LSTM_Whh = LSTM_Whh.multiply(scale_LSTM_Whh);
LSTM_bias = LSTM_bias.divide(127);
LSTM_bias = LSTM_bias.multiply(scale_LSTM_bias);
// settings
var num_units=500;
var N_mixture=20;
var input_size=3;
var W_full=nj.concatenate([LSTM_Wxh.T, LSTM_Whh.T]).T; // training size
var bias=LSTM_bias;
var forget_bias=1.0;
var h_w = output_w;
var h_b = output_b;
var scale_factor = 6.0;
var zero_state = function() {
return [nj.zeros(num_units), nj.zeros(num_units)];
};
var random_state = function() {
var std_ = 0.50;
var h = nj.zeros(num_units);
var c = nj.zeros(num_units);
var i = 0;
for(i=0;i<num_units;i++) {
h.set(i, randn(0, std_));
c.set(i, randn(0, std_));
}
return [h, c];
};
var copy_state = function(state) {
var h = state[0].clone();
var c = state[1].clone();
return [h, c];
};
var zero_input = function() {
return [0, 0, 0];
};
var random_input = function() {
var std_ = 0.1;
var x = nj.zeros(input_size);
var pen_s = 0;
if (randf(0, 1) > 0.9) pen_s = 1;
x.set(0, randn(0, std_));
x.set(1, randn(0, std_));
x.set(2, pen_s);
return x;
};
var update = function(x_, s) {
var x = nj.zeros(input_size);
x.set(0, x_[0]/scale_factor);
x.set(1, x_[1]/scale_factor);
x.set(2, x_[2]);
var h = s[0];
var c = s[1];
var concat = nj.concatenate([x, h]);
var hidden = nj.dot(concat, W_full);
hidden = nj.add(hidden, bias);
var i=nj.sigmoid(hidden.slice([0*num_units, 1*num_units]));
var g=nj.tanh(hidden.slice([1*num_units, 2*num_units]));
var f=nj.sigmoid(nj.add(hidden.slice([2*num_units, 3*num_units]), forget_bias));
var o=nj.sigmoid(hidden.slice([3*num_units, 4*num_units]));
var new_c = nj.add(nj.multiply(c, f), nj.multiply(g, i));
var new_h = nj.multiply(nj.tanh(new_c), o);
return [new_h, new_c];
}
var get_pdf = function(s) {
var h = s[0];
var NOUT = N_mixture;
var z=nj.add(nj.dot(h, h_w), h_b);
var z_eos = nj.sigmoid(z.slice([0, 1]));
var z_pi = z.slice([1+NOUT*0, 1+NOUT*1]);
var z_mu1 = z.slice([1+NOUT*1, 1+NOUT*2]);
var z_mu2 = z.slice([1+NOUT*2, 1+NOUT*3]);
var z_sigma1 = nj.exp(z.slice([1+NOUT*3, 1+NOUT*4]));
var z_sigma2 = nj.exp(z.slice([1+NOUT*4, 1+NOUT*5]));
var z_corr = nj.tanh(z.slice([1+NOUT*5, 1+NOUT*6]));
z_pi = nj.subtract(z_pi, z_pi.max());
z_pi = nj.softmax(z_pi);
return [z_pi, z_mu1, z_mu2, z_sigma1, z_sigma2, z_corr, z_eos];
};
var sample_pi_idx = function(z_pi) {
var x = randf(0, 1);
var N = N_mixture;
var accumulate = 0;
var i = 0;
for (i=0;i<N;i++) {
accumulate += z_pi.get(i);
if (accumulate >= x) {
return i;
}
}
console.log('error sampling pi index');
return -1;
};
var sample_eos = function(z_eos) {
// eos = 1 if random.random() < o_eos[0][0] else 0
var eos = 0;
if (randf(0, 1) < z_eos.get(0)) {
eos = 1;
}
return eos;
}
/*
def adjust_temp(pi_pdf, temp):
pi_pdf = np.log(pi_pdf) / temp
pi_pdf -= pi_pdf.max()
pi_pdf = np.exp(pi_pdf)
pi_pdf /= pi_pdf.sum()
return pi_pdf
*/
var adjust_temp = function(z_old, temp) {
var z = nj.array(z_old);
var i;
var x;
//console.log("before="+z_old.get(0));
for (i=z.shape[0]-1;i>=0;i--) {
x = z.get(i);
x = Math.log(x) / temp;
z.set(i, x);
}
x = z.max();
z = nj.subtract(z, x);
z = nj.exp(z);
x = z.sum();
z = nj.divide(z, x);
//console.log("after="+z.get(0));
return z;
};
var sample = function(z, temperature) {
// z is [z_pi, z_mu1, z_mu2, z_sigma1, z_sigma2, z_corr, z_eos]
// returns [x, y, eos]
var temp=0.65;
if (typeof(temperature) === "number") {
temp = temperature;
}
var z_0 = adjust_temp(z[0], temp);
var z_6 = nj.array(z[6]);
//var z6 = Math.exp(Math.log(z_6.get(0))/temp);
//z_6.set(0, z6);
var idx = sample_pi_idx(z_0);
var mu1 = z[1].get(idx);
var mu2 = z[2].get(idx);
var sigma1 = z[3].get(idx)*temp;
var sigma2 = z[4].get(idx)*temp;
var corr = z[5].get(idx);
var eos = sample_eos(z_6);
var delta = birandn(mu1, mu2, sigma1, sigma2, corr);
return [delta[0]*scale_factor, delta[1]*scale_factor, eos];
}
// Random numbers util (from https://github.com/karpathy/recurrentjs)
var return_v = false;
var v_val = 0.0;
var gaussRandom = function() {
if(return_v) {
return_v = false;
return v_val;
}
var u = 2*Math.random()-1;
var v = 2*Math.random()-1;
var r = u*u + v*v;
if(r == 0 || r > 1) return gaussRandom();
var c = Math.sqrt(-2*Math.log(r)/r);
v_val = v*c; // cache this
return_v = true;
return u*c;
}
var randf = function(a, b) { return Math.random()*(b-a)+a; };
var randi = function(a, b) { return Math.floor(Math.random()*(b-a)+a); };
var randn = function(mu, std){ return mu+gaussRandom()*std; };
// from http://www.math.grin.edu/~mooret/courses/math336/bivariate-normal.html
var birandn = function(mu1, mu2, std1, std2, rho) {
var z1 = randn(0, 1);
var z2 = randn(0, 1);
var x = Math.sqrt(1-rho*rho)*std1*z1 + rho*std1*z2 + mu1;
var y = std2*z2 + mu2;
return [x, y];
};
var set_scale_factor = function(scale) {
scale_factor = scale;
};
global.zero_state = zero_state;
global.zero_input = zero_input;
global.random_state = random_state;
global.copy_state = copy_state;
global.random_input = random_input;
global.update = update;
global.get_pdf = get_pdf;
global.randf = randf;
global.randi = randi;
global.randn = randn;
global.birandn = birandn;
global.sample = sample;
global.set_scale_factor = set_scale_factor;
})(Model);
(function(lib) {
"use strict";
if (typeof module === "undefined" || typeof module.exports === "undefined") {
//window.jsfeat = lib; // in ordinary browser attach library to window
} else {
module.exports = lib; // in nodejs
}
})(Model);
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.nj = f()}})(function(){var define,module,exports;return (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);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.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){
'use strict'
exports.toByteArray = toByteArray
exports.fromByteArray = fromByteArray
var lookup = []
var revLookup = []
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
function init () {
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for (var i = 0, len = code.length; i < len; ++i) {
lookup[i] = code[i]
revLookup[code.charCodeAt(i)] = i
}
revLookup['-'.charCodeAt(0)] = 62
revLookup['_'.charCodeAt(0)] = 63
}
init()
function toByteArray (b64) {
var i, j, l, tmp, placeHolders, arr
var len = b64.length
if (len % 4 > 0) {
throw new Error('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[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
// base64 is 4/3 + up to two characters of the original data
arr = new Arr(len * 3 / 4 - placeHolders)
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? len - 4 : len
var L = 0
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
arr[L++] = (tmp >> 16) & 0xFF
arr[L++] = (tmp >> 8) & 0xFF
arr[L++] = tmp & 0xFF
}
if (placeHolders === 2) {
tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
arr[L++] = tmp & 0xFF
} else if (placeHolders === 1) {
tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
arr[L++] = (tmp >> 8) & 0xFF
arr[L++] = tmp & 0xFF
}
return arr
}
function tripletToBase64 (num) {
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
}
function encodeChunk (uint8, start, end) {
var tmp
var output = []
for (var i = start; i < end; i += 3) {
tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output.push(tripletToBase64(tmp))
}
return output.join('')
}
function fromByteArray (uint8) {
var tmp
var len = uint8.length
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
var output = ''
var parts = []
var maxChunkLength = 16383 // must be multiple of 3
// go through the array every three bytes, we'll deal with trailing stuff later
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
}
// pad the end with zeros, but make sure to not forget the extra bytes
if (extraBytes === 1) {
tmp = uint8[len - 1]
output += lookup[tmp >> 2]
output += lookup[(tmp << 4) & 0x3F]
output += '=='
} else if (extraBytes === 2) {
tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
output += lookup[tmp >> 10]
output += lookup[(tmp >> 4) & 0x3F]
output += lookup[(tmp << 2) & 0x3F]
output += '='
}
parts.push(output)
return parts.join('')
}
},{}],2:[function(require,module,exports){
/**
* Bit twiddling hacks for JavaScript.
*
* Author: Mikola Lysenko
*
* Ported from Stanford bit twiddling hack library:
* http://graphics.stanford.edu/~seander/bithacks.html
*/
"use strict"; "use restrict";
//Number of bits in an integer
var INT_BITS = 32;
//Constants
exports.INT_BITS = INT_BITS;
exports.INT_MAX = 0x7fffffff;
exports.INT_MIN = -1<<(INT_BITS-1);
//Returns -1, 0, +1 depending on sign of x
exports.sign = function(v) {
return (v > 0) - (v < 0);
}
//Computes absolute value of integer
exports.abs = function(v) {
var mask = v >> (INT_BITS-1);
return (v ^ mask) - mask;
}
//Computes minimum of integers x and y
exports.min = function(x, y) {
return y ^ ((x ^ y) & -(x < y));
}
//Computes maximum of integers x and y
exports.max = function(x, y) {
return x ^ ((x ^ y) & -(x < y));
}
//Checks if a number is a power of two
exports.isPow2 = function(v) {
return !(v & (v-1)) && (!!v);
}
//Computes log base 2 of v
exports.log2 = function(v) {
var r, shift;
r = (v > 0xFFFF) << 4; v >>>= r;
shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift;
shift = (v > 0xF ) << 2; v >>>= shift; r |= shift;
shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift;
return r | (v >> 1);
}
//Computes log base 10 of v
exports.log10 = function(v) {
return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
(v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
(v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
}
//Counts number of bits
exports.popCount = function(v) {
v = v - ((v >>> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);
return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
}
//Counts number of trailing zeros
function countTrailingZeros(v) {
var c = 32;
v &= -v;
if (v) c--;
if (v & 0x0000FFFF) c -= 16;
if (v & 0x00FF00FF) c -= 8;
if (v & 0x0F0F0F0F) c -= 4;
if (v & 0x33333333) c -= 2;
if (v & 0x55555555) c -= 1;
return c;
}
exports.countTrailingZeros = countTrailingZeros;
//Rounds to next power of 2
exports.nextPow2 = function(v) {
v += v === 0;
--v;
v |= v >>> 1;
v |= v >>> 2;
v |= v >>> 4;
v |= v >>> 8;
v |= v >>> 16;
return v + 1;
}
//Rounds down to previous power of 2
exports.prevPow2 = function(v) {
v |= v >>> 1;
v |= v >>> 2;
v |= v >>> 4;
v |= v >>> 8;
v |= v >>> 16;
return v - (v>>>1);
}
//Computes parity of word
exports.parity = function(v) {
v ^= v >>> 16;
v ^= v >>> 8;
v ^= v >>> 4;
v &= 0xf;
return (0x6996 >>> v) & 1;
}
var REVERSE_TABLE = new Array(256);
(function(tab) {
for(var i=0; i<256; ++i) {
var v = i, r = i, s = 7;
for (v >>>= 1; v; v >>>= 1) {
r <<= 1;
r |= v & 1;
--s;
}
tab[i] = (r << s) & 0xff;
}
})(REVERSE_TABLE);
//Reverse bits in a 32 bit word
exports.reverse = function(v) {
return (REVERSE_TABLE[ v & 0xff] << 24) |
(REVERSE_TABLE[(v >>> 8) & 0xff] << 16) |
(REVERSE_TABLE[(v >>> 16) & 0xff] << 8) |
REVERSE_TABLE[(v >>> 24) & 0xff];
}
//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes
exports.interleave2 = function(x, y) {
x &= 0xFFFF;
x = (x | (x << 8)) & 0x00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F;
x = (x | (x << 2)) & 0x33333333;
x = (x | (x << 1)) & 0x55555555;
y &= 0xFFFF;
y = (y | (y << 8)) & 0x00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F;
y = (y | (y << 2)) & 0x33333333;
y = (y | (y << 1)) & 0x55555555;
return x | (y << 1);
}
//Extracts the nth interleaved component
exports.deinterleave2 = function(v, n) {
v = (v >>> n) & 0x55555555;
v = (v | (v >>> 1)) & 0x33333333;
v = (v | (v >>> 2)) & 0x0F0F0F0F;
v = (v | (v >>> 4)) & 0x00FF00FF;
v = (v | (v >>> 16)) & 0x000FFFF;
return (v << 16) >> 16;
}
//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes
exports.interleave3 = function(x, y, z) {
x &= 0x3FF;
x = (x | (x<<16)) & 4278190335;
x = (x | (x<<8)) & 251719695;
x = (x | (x<<4)) & 3272356035;
x = (x | (x<<2)) & 1227133513;
y &= 0x3FF;
y = (y | (y<<16)) & 4278190335;
y = (y | (y<<8)) & 251719695;
y = (y | (y<<4)) & 3272356035;
y = (y | (y<<2)) & 1227133513;
x |= (y << 1);
z &= 0x3FF;
z = (z | (z<<16)) & 4278190335;
z = (z | (z<<8)) & 251719695;
z = (z | (z<<4)) & 3272356035;
z = (z | (z<<2)) & 1227133513;
return x | (z << 2);
}
//Extracts nth interleaved component of a 3-tuple
exports.deinterleave3 = function(v, n) {
v = (v >>> n) & 1227133513;
v = (v | (v>>>2)) & 3272356035;
v = (v | (v>>>4)) & 251719695;
v = (v | (v>>>8)) & 4278190335;
v = (v | (v>>>16)) & 0x3FF;
return (v<<22)>>22;
}
//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page)
exports.nextCombination = function(v) {
var t = v | (v - 1);
return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1));
}
},{}],3:[function(require,module,exports){
(function (global){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
/* eslint-disable no-proto */
'use strict'
var base64 = require('base64-js')
var ieee754 = require('ieee754')
var isArray = require('isarray')
exports.Buffer = Buffer
exports.SlowBuffer = SlowBuffer
exports.INSPECT_MAX_BYTES = 50
/**
* If `Buffer.TYPED_ARRAY_SUPPORT`:
* === true Use Uint8Array implementation (fastest)
* === false Use Object implementation (most compatible, even IE6)
*
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
* Opera 11.6+, iOS 4.2+.
*
* Due to various browser bugs, sometimes the Object implementation will be used even
* when the browser supports typed arrays.
*
* Note:
*
* - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
* See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
*
* - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
*
* - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
* incorrect length in some situations.
* We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
* get the Object implementation, which is slower but behaves correctly.
*/
Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
? global.TYPED_ARRAY_SUPPORT
: typedArraySupport()
/*
* Export kMaxLength after typed array support is determined.
*/
exports.kMaxLength = kMaxLength()
function typedArraySupport () {
try {
var arr = new Uint8Array(1)
arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
return arr.foo() === 42 && // typed array instances can be augmented
typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
} catch (e) {
return false
}
}
function kMaxLength () {
return Buffer.TYPED_ARRAY_SUPPORT
? 0x7fffffff
: 0x3fffffff
}
function createBuffer (that, length) {
if (kMaxLength() < length) {
throw new RangeError('Invalid typed array length')
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
// Return an augmented `Uint8Array` instance, for best performance
that = new Uint8Array(length)
that.__proto__ = Buffer.prototype
} else {
// Fallback: Return an object instance of the Buffer class
if (that === null) {
that = new Buffer(length)
}
that.length = length
}
return that
}
/**
* The Buffer constructor returns instances of `Uint8Array` that have their
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods
* and the `Uint8Array` methods. Square bracket notation works as expected -- it
* returns a single octet.
*
* The `Uint8Array` prototype remains unmodified.
*/
function Buffer (arg, encodingOrOffset, length) {
if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
return new Buffer(arg, encodingOrOffset, length)
}
// Common case.
if (typeof arg === 'number') {
if (typeof encodingOrOffset === 'string') {
throw new Error(
'If encoding is specified then the first argument must be a string'
)
}
return allocUnsafe(this, arg)
}
return from(this, arg, encodingOrOffset, length)
}
Buffer.poolSize = 8192 // not used by this implementation
// TODO: Legacy, not needed anymore. Remove in next major version.
Buffer._augment = function (arr) {
arr.__proto__ = Buffer.prototype
return arr
}
function from (that, value, encodingOrOffset, length) {
if (typeof value === 'number') {
throw new TypeError('"value" argument must not be a number')
}
if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
return fromArrayBuffer(that, value, encodingOrOffset, length)
}
if (typeof value === 'string') {
return fromString(that, value, encodingOrOffset)
}
return fromObject(that, value)
}
/**
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
* if value is a number.
* Buffer.from(str[, encoding])
* Buffer.from(array)
* Buffer.from(buffer)
* Buffer.from(arrayBuffer[, byteOffset[, length]])
**/
Buffer.from = function (value, encodingOrOffset, length) {
return from(null, value, encodingOrOffset, length)
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
Buffer.prototype.__proto__ = Uint8Array.prototype
Buffer.__proto__ = Uint8Array
if (typeof Symbol !== 'undefined' && Symbol.species &&
Buffer[Symbol.species] === Buffer) {
// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
Object.defineProperty(Buffer, Symbol.species, {
value: null,
configurable: true
})
}
}
function assertSize (size) {
if (typeof size !== 'number') {
throw new TypeError('"size" argument must be a number')
} else if (size < 0) {
throw new RangeError('"size" argument must not be negative')
}
}
function alloc (that, size, fill, encoding) {
assertSize(size)
if (size <= 0) {
return createBuffer(that, size)
}
if (fill !== undefined) {
// Only pay attention to encoding if it's a string. This
// prevents accidentally sending in a number that would
// be interpretted as a start offset.
return typeof encoding === 'string'
? createBuffer(that, size).fill(fill, encoding)
: createBuffer(that, size).fill(fill)
}
return createBuffer(that, size)
}
/**
* Creates a new filled Buffer instance.
* alloc(size[, fill[, encoding]])
**/
Buffer.alloc = function (size, fill, encoding) {
return alloc(null, size, fill, encoding)
}
function allocUnsafe (that, size) {
assertSize(size)
that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
if (!Buffer.TYPED_ARRAY_SUPPORT) {
for (var i = 0; i < size; ++i) {
that[i] = 0
}
}
return that
}
/**
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
* */
Buffer.allocUnsafe = function (size) {
return allocUnsafe(null, size)
}
/**
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
*/
Buffer.allocUnsafeSlow = function (size) {
return allocUnsafe(null, size)
}
function fromString (that, string, encoding) {
if (typeof encoding !== 'string' || encoding === '') {
encoding = 'utf8'
}
if (!Buffer.isEncoding(encoding)) {
throw new TypeError('"encoding" must be a valid string encoding')
}
var length = byteLength(string, encoding) | 0
that = createBuffer(that, length)
var actual = that.write(string, encoding)
if (actual !== length) {
// Writing a hex string, for example, that contains invalid characters will
// cause everything after the first invalid character to be ignored. (e.g.
// 'abxxcd' will be treated as 'ab')
that = that.slice(0, actual)
}
return that
}
function fromArrayLike (that, array) {
var length = array.length < 0 ? 0 : checked(array.length) | 0
that = createBuffer(that, length)
for (var i = 0; i < length; i += 1) {
that[i] = array[i] & 255
}
return that
}
function fromArrayBuffer (that, array, byteOffset, length) {
array.byteLength // this throws if `array` is not a valid ArrayBuffer
if (byteOffset < 0 || array.byteLength < byteOffset) {
throw new RangeError('\'offset\' is out of bounds')
}
if (array.byteLength < byteOffset + (length || 0)) {
throw new RangeError('\'length\' is out of bounds')
}
if (byteOffset === undefined && length === undefined) {
array = new Uint8Array(array)
} else if (length === undefined) {
array = new Uint8Array(array, byteOffset)
} else {
array = new Uint8Array(array, byteOffset, length)
}
if (Buffer.TYPED_ARRAY_SUPPORT) {
// Return an augmented `Uint8Array` instance, for best performance
that = array
that.__proto__ = Buffer.prototype
} else {
// Fallback: Return an object instance of the Buffer class
that = fromArrayLike(that, array)
}
return that
}
function fromObject (that, obj) {
if (Buffer.isBuffer(obj)) {
var len = checked(obj.length) | 0
that = createBuffer(that, len)
if (that.length === 0) {
return that
}
obj.copy(that, 0, 0, len)
return that
}
if (obj) {
if ((typeof ArrayBuffer !== 'undefined' &&
obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
if (typeof obj.length !== 'number' || isnan(obj.length)) {
return createBuffer(that, 0)
}
return fromArrayLike(that, obj)
}
if (obj.type === 'Buffer' && isArray(obj.data)) {
return fromArrayLike(that, obj.data)
}
}
throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
}
function checked (length) {
// Note: cannot use `length < kMaxLength()` here because that fails when
// length is NaN (which is otherwise coerced to zero.)
if (length >= kMaxLength()) {
throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
'size: 0x' + kMaxLength().toString(16) + ' bytes')
}
return length | 0
}
function SlowBuffer (length) {
if (+length != length) { // eslint-disable-line eqeqeq
length = 0
}
return Buffer.alloc(+length)
}
Buffer.isBuffer = function isBuffer (b) {
return !!(b != null && b._isBuffer)
}
Buffer.compare = function compare (a, b) {
if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
throw new TypeError('Arguments must be Buffers')
}
if (a === b) return 0
var x = a.length
var y = b.length
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i]
y = b[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
Buffer.isEncoding = function isEncoding (encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'latin1':
case 'binary':
case 'base64':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true
default:
return false
}
}
Buffer.concat = function concat (list, length) {
if (!isArray(list)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
if (list.length === 0) {
return Buffer.alloc(0)
}
var i
if (length === undefined) {
length = 0
for (i = 0; i < list.length; ++i) {
length += list[i].length
}
}
var buffer = Buffer.allocUnsafe(length)
var pos = 0
for (i = 0; i < list.length; ++i) {
var buf = list[i]
if (!Buffer.isBuffer(buf)) {
throw new TypeError('"list" argument must be an Array of Buffers')
}
buf.copy(buffer, pos)
pos += buf.length
}
return buffer
}
function byteLength (string, encoding) {
if (Buffer.isBuffer(string)) {
return string.length
}
if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
(ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
return string.byteLength
}
if (typeof string !== 'string') {
string = '' + string
}
var len = string.length
if (len === 0) return 0
// Use a for loop to avoid recursion
var loweredCase = false
for (;;) {
switch (encoding) {
case 'ascii':
case 'latin1':
case 'binary':
return len
case 'utf8':
case 'utf-8':
case undefined:
return utf8ToBytes(string).length
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return len * 2
case 'hex':
return len >>> 1
case 'base64':
return base64ToBytes(string).length
default:
if (loweredCase) return utf8ToBytes(string).length // assume utf8
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.byteLength = byteLength
function slowToString (encoding, start, end) {
var loweredCase = false
// No need to verify that "this.length <= MAX_UINT32" since it's a read-only
// property of a typed array.
// This behaves neither like String nor Uint8Array in that we set start/end
// to their upper/lower bounds if the value passed is out of range.
// undefined is handled specially as per ECMA-262 6th Edition,
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
if (start === undefined || start < 0) {
start = 0
}
// Return early if start > this.length. Done here to prevent potential uint32
// coercion fail below.
if (start > this.length) {
return ''
}
if (end === undefined || end > this.length) {
end = this.length
}
if (end <= 0) {
return ''
}
// Force coersion to uint32. This will also coerce falsey/NaN values to 0.
end >>>= 0
start >>>= 0
if (end <= start) {
return ''
}
if (!encoding) encoding = 'utf8'
while (true) {
switch (encoding) {
case 'hex':
return hexSlice(this, start, end)
case 'utf8':
case 'utf-8':
return utf8Slice(this, start, end)
case 'ascii':
return asciiSlice(this, start, end)
case 'latin1':
case 'binary':
return latin1Slice(this, start, end)
case 'base64':
return base64Slice(this, start, end)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return utf16leSlice(this, start, end)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = (encoding + '').toLowerCase()
loweredCase = true
}
}
}
// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
// Buffer instances.
Buffer.prototype._isBuffer = true
function swap (b, n, m) {
var i = b[n]
b[n] = b[m]
b[m] = i
}
Buffer.prototype.swap16 = function swap16 () {
var len = this.length
if (len % 2 !== 0) {
throw new RangeError('Buffer size must be a multiple of 16-bits')
}
for (var i = 0; i < len; i += 2) {
swap(this, i, i + 1)
}
return this
}
Buffer.prototype.swap32 = function swap32 () {
var len = this.length
if (len % 4 !== 0) {
throw new RangeError('Buffer size must be a multiple of 32-bits')
}
for (var i = 0; i < len; i += 4) {
swap(this, i, i + 3)
swap(this, i + 1, i + 2)
}
return this
}
Buffer.prototype.swap64 = function swap64 () {
var len = this.length
if (len % 8 !== 0) {
throw new RangeError('Buffer size must be a multiple of 64-bits')
}
for (var i = 0; i < len; i += 8) {
swap(this, i, i + 7)
swap(this, i + 1, i + 6)
swap(this, i + 2, i + 5)
swap(this, i + 3, i + 4)
}
return this
}
Buffer.prototype.toString = function toString () {
var length = this.length | 0
if (length === 0) return ''
if (arguments.length === 0) return utf8Slice(this, 0, length)
return slowToString.apply(this, arguments)
}
Buffer.prototype.equals = function equals (b) {
if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
if (this === b) return true
return Buffer.compare(this, b) === 0
}
Buffer.prototype.inspect = function inspect () {
var str = ''
var max = exports.INSPECT_MAX_BYTES
if (this.length > 0) {
str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
if (this.length > max) str += ' ... '
}
return '<Buffer ' + str + '>'
}
Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
if (!Buffer.isBuffer(target)) {
throw new TypeError('Argument must be a Buffer')
}
if (start === undefined) {
start = 0
}
if (end === undefined) {
end = target ? target.length : 0
}
if (thisStart === undefined) {
thisStart = 0
}
if (thisEnd === undefined) {
thisEnd = this.length
}
if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
throw new RangeError('out of range index')
}
if (thisStart >= thisEnd && start >= end) {
return 0
}
if (thisStart >= thisEnd) {
return -1
}
if (start >= end) {
return 1
}
start >>>= 0
end >>>= 0
thisStart >>>= 0
thisEnd >>>= 0
if (this === target) return 0
var x = thisEnd - thisStart
var y = end - start
var len = Math.min(x, y)
var thisCopy = this.slice(thisStart, thisEnd)
var targetCopy = target.slice(start, end)
for (var i = 0; i < len; ++i) {
if (thisCopy[i] !== targetCopy[i]) {
x = thisCopy[i]
y = targetCopy[i]
break
}
}
if (x < y) return -1
if (y < x) return 1
return 0
}
// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
//
// Arguments:
// - buffer - a Buffer to search
// - val - a string, Buffer, or number
// - byteOffset - an index into `buffer`; will be clamped to an int32
// - encoding - an optional encoding, relevant is val is a string
// - dir - true for indexOf, false for lastIndexOf
function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
// Empty buffer means no match
if (buffer.length === 0) return -1
// Normalize byteOffset
if (typeof byteOffset === 'string') {
encoding = byteOffset
byteOffset = 0
} else if (byteOffset > 0x7fffffff) {
byteOffset = 0x7fffffff
} else if (byteOffset < -0x80000000) {
byteOffset = -0x80000000
}
byteOffset = +byteOffset // Coerce to Number.
if (isNaN(byteOffset)) {
// byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
byteOffset = dir ? 0 : (buffer.length - 1)
}
// Normalize byteOffset: negative offsets start from the end of the buffer
if (byteOffset < 0) byteOffset = buffer.length + byteOffset
if (byteOffset >= buffer.length) {
if (dir) return -1
else byteOffset = buffer.length - 1
} else if (byteOffset < 0) {
if (dir) byteOffset = 0
else return -1
}
// Normalize val
if (typeof val === 'string') {
val = Buffer.from(val, encoding)
}
// Finally, search either indexOf (if dir is true) or lastIndexOf
if (Buffer.isBuffer(val)) {
// Special case: looking for empty string/buffer always fails
if (val.length === 0) {
return -1
}
return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
} else if (typeof val === 'number') {
val = val & 0xFF // Search for a byte value [0-255]
if (Buffer.TYPED_ARRAY_SUPPORT &&
typeof Uint8Array.prototype.indexOf === 'function') {
if (dir) {
return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
} else {
return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
}
}
return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
}
throw new TypeError('val must be string, number or Buffer')
}
function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
var indexSize = 1
var arrLength = arr.length
var valLength = val.length
if (encoding !== undefined) {
encoding = String(encoding).toLowerCase()
if (encoding === 'ucs2' || encoding === 'ucs-2' ||
encoding === 'utf16le' || encoding === 'utf-16le') {
if (arr.length < 2 || val.length < 2) {
return -1
}
indexSize = 2
arrLength /= 2
valLength /= 2
byteOffset /= 2
}
}
function read (buf, i) {
if (indexSize === 1) {
return buf[i]
} else {
return buf.readUInt16BE(i * indexSize)
}
}
var i
if (dir) {
var foundIndex = -1
for (i = byteOffset; i < arrLength; i++) {
if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
if (foundIndex === -1) foundIndex = i
if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
} else {
if (foundIndex !== -1) i -= i - foundIndex
foundIndex = -1
}
}
} else {
if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
for (i = byteOffset; i >= 0; i--) {
var found = true
for (var j = 0; j < valLength; j++) {
if (read(arr, i + j) !== read(val, j)) {
found = false
break
}
}
if (found) return i
}
}
return -1
}
Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
return this.indexOf(val, byteOffset, encoding) !== -1
}
Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
}
Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
}
function hexWrite (buf, string, offset, length) {
offset = Number(offset) || 0
var remaining = buf.length - offset
if (!length) {
length = remaining
} else {
length = Number(length)
if (length > remaining) {
length = remaining
}
}
// must be an even number of digits
var strLen = string.length
if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')
if (length > strLen / 2) {
length = strLen / 2
}
for (var i = 0; i < length; ++i) {
var parsed = parseInt(string.substr(i * 2, 2), 16)
if (isNaN(parsed)) return i
buf[offset + i] = parsed
}
return i
}
function utf8Write (buf, string, offset, length) {
return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
}
function asciiWrite (buf, string, offset, length) {
return blitBuffer(asciiToBytes(string), buf, offset, length)
}
function latin1Write (buf, string, offset, length) {
return asciiWrite(buf, string, offset, length)
}
function base64Write (buf, string, offset, length) {
return blitBuffer(base64ToBytes(string), buf, offset, length)
}
function ucs2Write (buf, string, offset, length) {
return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
}
Buffer.prototype.write = function write (string, offset, length, encoding) {
// Buffer#write(string)
if (offset === undefined) {
encoding = 'utf8'
length = this.length
offset = 0
// Buffer#write(string, encoding)
} else if (length === undefined && typeof offset === 'string') {
encoding = offset
length = this.length
offset = 0
// Buffer#write(string, offset[, length][, encoding])
} else if (isFinite(offset)) {
offset = offset | 0
if (isFinite(length)) {
length = length | 0
if (encoding === undefined) encoding = 'utf8'
} else {
encoding = length
length = undefined
}
// legacy write(string, encoding, offset, length) - remove in v0.13
} else {
throw new Error(
'Buffer.write(string, encoding, offset[, length]) is no longer supported'
)
}
var remaining = this.length - offset
if (length === undefined || length > remaining) length = remaining
if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
throw new RangeError('Attempt to write outside buffer bounds')
}
if (!encoding) encoding = 'utf8'
var loweredCase = false
for (;;) {
switch (encoding) {
case 'hex':
return hexWrite(this, string, offset, length)
case 'utf8':
case 'utf-8':
return utf8Write(this, string, offset, length)
case 'ascii':
return asciiWrite(this, string, offset, length)
case 'latin1':
case 'binary':
return latin1Write(this, string, offset, length)
case 'base64':
// Warning: maxLength not taken into account in base64Write
return base64Write(this, string, offset, length)
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return ucs2Write(this, string, offset, length)
default:
if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
encoding = ('' + encoding).toLowerCase()
loweredCase = true
}
}
}
Buffer.prototype.toJSON = function toJSON () {
return {
type: 'Buffer',
data: Array.prototype.slice.call(this._arr || this, 0)
}
}
function base64Slice (buf, start, end) {
if (start === 0 && end === buf.length) {
return base64.fromByteArray(buf)
} else {
return base64.fromByteArray(buf.slice(start, end))
}
}
function utf8Slice (buf, start, end) {
end = Math.min(buf.length, end)
var res = []
var i = start
while (i < end) {
var firstByte = buf[i]
var codePoint = null
var bytesPerSequence = (firstByte > 0xEF) ? 4
: (firstByte > 0xDF) ? 3
: (firstByte > 0xBF) ? 2
: 1
if (i + bytesPerSequence <= end) {
var secondByte, thirdByte, fourthByte, tempCodePoint
switch (bytesPerSequence) {
case 1:
if (firstByte < 0x80) {
codePoint = firstByte
}
break
case 2:
secondByte = buf[i + 1]
if ((secondByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
if (tempCodePoint > 0x7F) {
codePoint = tempCodePoint
}
}
break
case 3:
secondByte = buf[i + 1]
thirdByte = buf[i + 2]
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
codePoint = tempCodePoint
}
}
break
case 4:
secondByte = buf[i + 1]
thirdByte = buf[i + 2]
fourthByte = buf[i + 3]
if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
codePoint = tempCodePoint
}
}
}
}
if (codePoint === null) {
// we did not generate a valid codePoint so insert a
// replacement char (U+FFFD) and advance only 1 byte
codePoint = 0xFFFD
bytesPerSequence = 1
} else if (codePoint > 0xFFFF) {
// encode to utf16 (surrogate pair dance)
codePoint -= 0x10000
res.push(codePoint >>> 10 & 0x3FF | 0xD800)
codePoint = 0xDC00 | codePoint & 0x3FF
}
res.push(codePoint)
i += bytesPerSequence
}
return decodeCodePointsArray(res)
}
// Based on http://stackoverflow.com/a/22747272/680742, the browser with
// the lowest limit is Chrome, with 0x10000 args.
// We go 1 magnitude less, for safety
var MAX_ARGUMENTS_LENGTH = 0x1000
function decodeCodePointsArray (codePoints) {
var len = codePoints.length
if (len <= MAX_ARGUMENTS_LENGTH) {
return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
}
// Decode in chunks to avoid "call stack size exceeded".
var res = ''
var i = 0
while (i < len) {
res += String.fromCharCode.apply(
String,
codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
)
}
return res
}
function asciiSlice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; ++i) {
ret += String.fromCharCode(buf[i] & 0x7F)
}
return ret
}
function latin1Slice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; ++i) {
ret += String.fromCharCode(buf[i])
}
return ret
}
function hexSlice (buf, start, end) {
var len = buf.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(buf[i])
}
return out
}
function utf16leSlice (buf, start, end) {
var bytes = buf.slice(start, end)
var res = ''
for (var i = 0; i < bytes.length; i += 2) {
res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
}
return res
}
Buffer.prototype.slice = function slice (start, end) {
var len = this.length
start = ~~start
end = end === undefined ? len : ~~end
if (start < 0) {
start += len
if (start < 0) start = 0
} else if (start > len) {
start = len
}
if (end < 0) {
end += len
if (end < 0) end = 0
} else if (end > len) {
end = len
}
if (end < start) end = start
var newBuf
if (Buffer.TYPED_ARRAY_SUPPORT) {
newBuf = this.subarray(start, end)
newBuf.__proto__ = Buffer.prototype
} else {
var sliceLen = end - start
newBuf = new Buffer(sliceLen, undefined)
for (var i = 0; i < sliceLen; ++i) {
newBuf[i] = this[i + start]
}
}
return newBuf
}
/*
* Need to make sure that buffer isn't trying to write out of bounds.
*/
function checkOffset (offset, ext, length) {
if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
}
Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
return val
}
Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) {
checkOffset(offset, byteLength, this.length)
}
var val = this[offset + --byteLength]
var mul = 1
while (byteLength > 0 && (mul *= 0x100)) {
val += this[offset + --byteLength] * mul
}
return val
}
Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
if (!noAssert) checkOffset(offset, 1, this.length)
return this[offset]
}
Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
return this[offset] | (this[offset + 1] << 8)
}
Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
return (this[offset] << 8) | this[offset + 1]
}
Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ((this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16)) +
(this[offset + 3] * 0x1000000)
}
Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] * 0x1000000) +
((this[offset + 1] << 16) |
(this[offset + 2] << 8) |
this[offset + 3])
}
Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var val = this[offset]
var mul = 1
var i = 0
while (++i < byteLength && (mul *= 0x100)) {
val += this[offset + i] * mul
}
mul *= 0x80
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
return val
}
Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) checkOffset(offset, byteLength, this.length)
var i = byteLength
var mul = 1
var val = this[offset + --i]
while (i > 0 && (mul *= 0x100)) {
val += this[offset + --i] * mul
}
mul *= 0x80
if (val >= mul) val -= Math.pow(2, 8 * byteLength)
return val
}
Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
if (!noAssert) checkOffset(offset, 1, this.length)
if (!(this[offset] & 0x80)) return (this[offset])
return ((0xff - this[offset] + 1) * -1)
}
Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
var val = this[offset] | (this[offset + 1] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 2, this.length)
var val = this[offset + 1] | (this[offset] << 8)
return (val & 0x8000) ? val | 0xFFFF0000 : val
}
Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset]) |
(this[offset + 1] << 8) |
(this[offset + 2] << 16) |
(this[offset + 3] << 24)
}
Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return (this[offset] << 24) |
(this[offset + 1] << 16) |
(this[offset + 2] << 8) |
(this[offset + 3])
}
Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, true, 23, 4)
}
Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 4, this.length)
return ieee754.read(this, offset, false, 23, 4)
}
Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, true, 52, 8)
}
Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
if (!noAssert) checkOffset(offset, 8, this.length)
return ieee754.read(this, offset, false, 52, 8)
}
function checkInt (buf, value, offset, ext, max, min) {
if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
if (offset + ext > buf.length) throw new RangeError('Index out of range')
}
Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) {
var maxBytes = Math.pow(2, 8 * byteLength) - 1
checkInt(this, value, offset, byteLength, maxBytes, 0)
}
var mul = 1
var i = 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100)) {
this[offset + i] = (value / mul) & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
byteLength = byteLength | 0
if (!noAssert) {
var maxBytes = Math.pow(2, 8 * byteLength) - 1
checkInt(this, value, offset, byteLength, maxBytes, 0)
}
var i = byteLength - 1
var mul = 1
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100)) {
this[offset + i] = (value / mul) & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
this[offset] = (value & 0xff)
return offset + 1
}
function objectWriteUInt16 (buf, value, offset, littleEndian) {
if (value < 0) value = 0xffff + value + 1
for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
(littleEndian ? i : 1 - i) * 8
}
}
Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
} else {
objectWriteUInt16(this, value, offset, true)
}
return offset + 2
}
Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 8)
this[offset + 1] = (value & 0xff)
} else {
objectWriteUInt16(this, value, offset, false)
}
return offset + 2
}
function objectWriteUInt32 (buf, value, offset, littleEndian) {
if (value < 0) value = 0xffffffff + value + 1
for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
}
}
Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset + 3] = (value >>> 24)
this[offset + 2] = (value >>> 16)
this[offset + 1] = (value >>> 8)
this[offset] = (value & 0xff)
} else {
objectWriteUInt32(this, value, offset, true)
}
return offset + 4
}
Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = (value & 0xff)
} else {
objectWriteUInt32(this, value, offset, false)
}
return offset + 4
}
Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) {
var limit = Math.pow(2, 8 * byteLength - 1)
checkInt(this, value, offset, byteLength, limit - 1, -limit)
}
var i = 0
var mul = 1
var sub = 0
this[offset] = value & 0xFF
while (++i < byteLength && (mul *= 0x100)) {
if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
sub = 1
}
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) {
var limit = Math.pow(2, 8 * byteLength - 1)
checkInt(this, value, offset, byteLength, limit - 1, -limit)
}
var i = byteLength - 1
var mul = 1
var sub = 0
this[offset + i] = value & 0xFF
while (--i >= 0 && (mul *= 0x100)) {
if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
sub = 1
}
this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
}
return offset + byteLength
}
Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
if (value < 0) value = 0xff + value + 1
this[offset] = (value & 0xff)
return offset + 1
}
Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
} else {
objectWriteUInt16(this, value, offset, true)
}
return offset + 2
}
Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 8)
this[offset + 1] = (value & 0xff)
} else {
objectWriteUInt16(this, value, offset, false)
}
return offset + 2
}
Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value & 0xff)
this[offset + 1] = (value >>> 8)
this[offset + 2] = (value >>> 16)
this[offset + 3] = (value >>> 24)
} else {
objectWriteUInt32(this, value, offset, true)
}
return offset + 4
}
Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
value = +value
offset = offset | 0
if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
if (value < 0) value = 0xffffffff + value + 1
if (Buffer.TYPED_ARRAY_SUPPORT) {
this[offset] = (value >>> 24)
this[offset + 1] = (value >>> 16)
this[offset + 2] = (value >>> 8)
this[offset + 3] = (value & 0xff)
} else {
objectWriteUInt32(this, value, offset, false)
}
return offset + 4
}
function checkIEEE754 (buf, value, offset, ext, max, min) {
if (offset + ext > buf.length) throw new RangeError('Index out of range')
if (offset < 0) throw new RangeError('Index out of range')
}
function writeFloat (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
}
ieee754.write(buf, value, offset, littleEndian, 23, 4)
return offset + 4
}
Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
return writeFloat(this, value, offset, true, noAssert)
}
Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
return writeFloat(this, value, offset, false, noAssert)
}
function writeDouble (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
}
ieee754.write(buf, value, offset, littleEndian, 52, 8)
return offset + 8
}
Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
return writeDouble(this, value, offset, true, noAssert)
}
Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
return writeDouble(this, value, offset, false, noAssert)
}
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function copy (target, targetStart, start, end) {
if (!start) start = 0
if (!end && end !== 0) end = this.length
if (targetStart >= target.length) targetStart = target.length
if (!targetStart) targetStart = 0
if (end > 0 && end < start) end = start
// Copy 0 bytes; we're done
if (end === start) return 0
if (target.length === 0 || this.length === 0) return 0
// Fatal error conditions
if (targetStart < 0) {
throw new RangeError('targetStart out of bounds')
}
if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
if (end < 0) throw new RangeError('sourceEnd out of bounds')
// Are we oob?
if (end > this.length) end = this.length
if (target.length - targetStart < end - start) {
end = target.length - targetStart + start
}
var len = end - start
var i
if (this === target && start < targetStart && targetStart < end) {
// descending copy from end
for (i = len - 1; i >= 0; --i) {
target[i + targetStart] = this[i + start]
}
} else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
// ascending copy from start
for (i = 0; i < len; ++i) {
target[i + targetStart] = this[i + start]
}
} else {
Uint8Array.prototype.set.call(
target,
this.subarray(start, start + len),
targetStart
)
}
return len
}
// Usage:
// buffer.fill(number[, offset[, end]])
// buffer.fill(buffer[, offset[, end]])
// buffer.fill(string[, offset[, end]][, encoding])
Buffer.prototype.fill = function fill (val, start, end, encoding) {
// Handle string cases:
if (typeof val === 'string') {
if (typeof start === 'string') {
encoding = start
start = 0
end = this.length
} else if (typeof end === 'string') {
encoding = end
end = this.length
}
if (val.length === 1) {
var code = val.charCodeAt(0)
if (code < 256) {
val = code
}
}
if (encoding !== undefined && typeof encoding !== 'string') {
throw new TypeError('encoding must be a string')
}
if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
throw new TypeError('Unknown encoding: ' + encoding)
}
} else if (typeof val === 'number') {
val = val & 255
}
// Invalid ranges are not set to a default, so can range check early.
if (start < 0 || this.length < start || this.length < end) {
throw new RangeError('Out of range index')
}
if (end <= start) {
return this
}
start = start >>> 0
end = end === undefined ? this.length : end >>> 0
if (!val) val = 0
var i
if (typeof val === 'number') {
for (i = start; i < end; ++i) {
this[i] = val
}
} else {
var bytes = Buffer.isBuffer(val)
? val
: utf8ToBytes(new Buffer(val, encoding).toString())
var len = bytes.length
for (i = 0; i < end - start; ++i) {
this[i + start] = bytes[i % len]
}
}
return this
}
// HELPER FUNCTIONS
// ================
var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
function base64clean (str) {
// Node strips out invalid characters like \n and \t from the string, base64-js does not
str = stringtrim(str).replace(INVALID_BASE64_RE, '')
// Node converts strings with length < 2 to ''
if (str.length < 2) return ''
// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
while (str.length % 4 !== 0) {
str = str + '='
}
return str
}
function stringtrim (str) {
if (str.trim) return str.trim()
return str.replace(/^\s+|\s+$/g, '')
}
function toHex (n) {
if (n < 16) return '0' + n.toString(16)
return n.toString(16)
}
function utf8ToBytes (string, units) {
units = units || Infinity
var codePoint
var length = string.length
var leadSurrogate = null
var bytes = []
for (var i = 0; i < length; ++i) {
codePoint = string.charCodeAt(i)
// is surrogate component
if (codePoint > 0xD7FF && codePoint < 0xE000) {
// last char was a lead
if (!leadSurrogate) {
// no lead yet
if (codePoint > 0xDBFF) {
// unexpected trail
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
} else if (i + 1 === length) {
// unpaired lead
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
continue
}
// valid lead
leadSurrogate = codePoint
continue
}
// 2 leads in a row
if (codePoint < 0xDC00) {
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
leadSurrogate = codePoint
continue
}
// valid surrogate pair
codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
} else if (leadSurrogate) {
// valid bmp char, but last char was a lead
if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
}
leadSurrogate = null
// encode utf8
if (codePoint < 0x80) {
if ((units -= 1) < 0) break
bytes.push(codePoint)
} else if (codePoint < 0x800) {
if ((units -= 2) < 0) break
bytes.push(
codePoint >> 0x6 | 0xC0,
codePoint & 0x3F | 0x80
)
} else if (codePoint < 0x10000) {
if ((units -= 3) < 0) break
bytes.push(
codePoint >> 0xC | 0xE0,
codePoint >> 0x6 & 0x3F | 0x80,
codePoint & 0x3F | 0x80
)
} else if (codePoint < 0x110000) {
if ((units -= 4) < 0) break
bytes.push(
codePoint >> 0x12 | 0xF0,
codePoint >> 0xC & 0x3F | 0x80,
codePoint >> 0x6 & 0x3F | 0x80,
codePoint & 0x3F | 0x80
)
} else {
throw new Error('Invalid code point')
}
}
return bytes
}
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 utf16leToBytes (str, units) {
var c, hi, lo
var byteArray = []
for (var i = 0; i < str.length; ++i) {
if ((units -= 2) < 0) break
c = str.charCodeAt(i)
hi = c >> 8
lo = c % 256
byteArray.push(lo)
byteArray.push(hi)
}
return byteArray
}
function base64ToBytes (str) {
return base64.toByteArray(base64clean(str))
}
function blitBuffer (src, dst, offset, length) {
for (var i = 0; i < length; ++i) {
if ((i + offset >= dst.length) || (i >= src.length)) break
dst[i + offset] = src[i]
}
return i
}
function isnan (val) {
return val !== val // eslint-disable-line no-self-compare
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"base64-js":1,"ieee754":10,"isarray":4}],4:[function(require,module,exports){
var toString = {}.toString;
module.exports = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};
},{}],5:[function(require,module,exports){
"use strict"
var createThunk = require("./lib/thunk.js")
function Procedure() {
this.argTypes = []
this.shimArgs = []
this.arrayArgs = []
this.arrayBlockIndices = []
this.scalarArgs = []
this.offsetArgs = []
this.offsetArgIndex = []
this.indexArgs = []
this.shapeArgs = []
this.funcName = ""
this.pre = null
this.body = null
this.post = null
this.debug = false
}
function compileCwise(user_args) {
//Create procedure
var proc = new Procedure()
//Parse blocks
proc.pre = user_args.pre
proc.body = user_args.body
proc.post = user_args.post
//Parse arguments
var proc_args = user_args.args.slice(0)
proc.argTypes = proc_args
for(var i=0; i<proc_args.length; ++i) {
var arg_type = proc_args[i]
if(arg_type === "array" || (typeof arg_type === "object" && arg_type.blockIndices)) {
proc.argTypes[i] = "array"
proc.arrayArgs.push(i)
proc.arrayBlockIndices.push(arg_type.blockIndices ? arg_type.blockIndices : 0)
proc.shimArgs.push("array" + i)
if(i < proc.pre.args.length && proc.pre.args[i].count>0) {
throw new Error("cwise: pre() block may not reference array args")
}
if(i < proc.post.args.length && proc.post.args[i].count>0) {
throw new Error("cwise: post() block may not reference array args")
}
} else if(arg_type === "scalar") {
proc.scalarArgs.push(i)
proc.shimArgs.push("scalar" + i)
} else if(arg_type === "index") {
proc.indexArgs.push(i)
if(i < proc.pre.args.length && proc.pre.args[i].count > 0) {
throw new Error("cwise: pre() block may not reference array index")
}
if(i < proc.body.args.length && proc.body.args[i].lvalue) {
throw new Error("cwise: body() block may not write to array index")
}
if(i < proc.post.args.length && proc.post.args[i].count > 0) {
throw new Error("cwise: post() block may not reference array index")
}
} else if(arg_type === "shape") {
proc.shapeArgs.push(i)
if(i < proc.pre.args.length && proc.pre.args[i].lvalue) {
throw new Error("cwise: pre() block may not write to array shape")
}
if(i < proc.body.args.length && proc.body.args[i].lvalue) {
throw new Error("cwise: body() block may not write to array shape")
}
if(i < proc.post.args.length && proc.post.args[i].lvalue) {
throw new Error("cwise: post() block may not write to array shape")
}
} else if(typeof arg_type === "object" && arg_type.offset) {
proc.argTypes[i] = "offset"
proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset })
proc.offsetArgIndex.push(i)
} else {
throw new Error("cwise: Unknown argument type " + proc_args[i])
}
}
//Make sure at least one array argument was specified
if(proc.arrayArgs.length <= 0) {
throw new Error("cwise: No array arguments specified")
}
//Make sure arguments are correct
if(proc.pre.args.length > proc_args.length) {
throw new Error("cwise: Too many arguments in pre() block")
}
if(proc.body.args.length > proc_args.length) {
throw new Error("cwise: Too many arguments in body() block")
}
if(proc.post.args.length > proc_args.length) {
throw new Error("cwise: Too many arguments in post() block")
}
//Check debug flag
proc.debug = !!user_args.printCode || !!user_args.debug
//Retrieve name
proc.funcName = user_args.funcName || "cwise"
//Read in block size
proc.blockSize = user_args.blockSize || 64
return createThunk(proc)
}
module.exports = compileCwise
},{"./lib/thunk.js":7}],6:[function(require,module,exports){
"use strict"
var uniq = require("uniq")
// This function generates very simple loops analogous to how you typically traverse arrays (the outermost loop corresponds to the slowest changing index, the innermost loop to the fastest changing index)
// TODO: If two arrays have the same strides (and offsets) there is potential for decreasing the number of "pointers" and related variables. The drawback is that the type signature would become more specific and that there would thus be less potential for caching, but it might still be worth it, especially when dealing with large numbers of arguments.
function innerFill(order, proc, body) {
var dimension = order.length
, nargs = proc.arrayArgs.length
, has_index = proc.indexArgs.length>0
, code = []
, vars = []
, idx=0, pidx=0, i, j
for(i=0; i<dimension; ++i) { // Iteration variables
vars.push(["i",i,"=0"].join(""))
}
//Compute scan deltas
for(j=0; j<nargs; ++j) {
for(i=0; i<dimension; ++i) {
pidx = idx
idx = order[i]
if(i === 0) { // The innermost/fastest dimension's delta is simply its stride
vars.push(["d",j,"s",i,"=t",j,"p",idx].join(""))
} else { // For other dimensions the delta is basically the stride minus something which essentially "rewinds" the previous (more inner) dimension
vars.push(["d",j,"s",i,"=(t",j,"p",idx,"-s",pidx,"*t",j,"p",pidx,")"].join(""))
}
}
}
code.push("var " + vars.join(","))
//Scan loop
for(i=dimension-1; i>=0; --i) { // Start at largest stride and work your way inwards
idx = order[i]
code.push(["for(i",i,"=0;i",i,"<s",idx,";++i",i,"){"].join(""))
}
//Push body of inner loop
code.push(body)
//Advance scan pointers
for(i=0; i<dimension; ++i) {
pidx = idx
idx = order[i]
for(j=0; j<nargs; ++j) {
code.push(["p",j,"+=d",j,"s",i].join(""))
}
if(has_index) {
if(i > 0) {
code.push(["index[",pidx,"]-=s",pidx].join(""))
}
code.push(["++index[",idx,"]"].join(""))
}
code.push("}")
}
return code.join("\n")
}
// Generate "outer" loops that loop over blocks of data, applying "inner" loops to the blocks by manipulating the local variables in such a way that the inner loop only "sees" the current block.
// TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary.
// I believe the s* are not used elsewhere (in particular, I don't think they're used in the pre/post parts and "shape" is defined independently), so it would be possible to make defining the s* dependent on what loop method is being used.
function outerFill(matched, order, proc, body) {
var dimension = order.length
, nargs = proc.arrayArgs.length
, blockSize = proc.blockSize
, has_index = proc.indexArgs.length > 0
, code = []
for(var i=0; i<nargs; ++i) {
code.push(["var offset",i,"=p",i].join(""))
}
//Generate loops for unmatched dimensions
// The order in which these dimensions are traversed is fairly arbitrary (from small stride to large stride, for the first argument)
// TODO: It would be nice if the order in which these loops are placed would also be somehow "optimal" (at the very least we should check that it really doesn't hurt us if they're not).
for(var i=matched; i<dimension; ++i) {
code.push(["for(var j"+i+"=SS[", order[i], "]|0;j", i, ">0;){"].join("")) // Iterate back to front
code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j).
code.push(["s",order[i],"=j",i].join(""))
code.push(["j",i,"=0"].join(""))
code.push(["}else{s",order[i],"=",blockSize].join(""))
code.push(["j",i,"-=",blockSize,"}"].join(""))
if(has_index) {
code.push(["index[",order[i],"]=j",i].join(""))
}
}
for(var i=0; i<nargs; ++i) {
var indexStr = ["offset"+i]
for(var j=matched; j<dimension; ++j) {
indexStr.push(["j",j,"*t",i,"p",order[j]].join(""))
}
code.push(["p",i,"=(",indexStr.join("+"),")"].join(""))
}
code.push(innerFill(order, proc, body))
for(var i=matched; i<dimension; ++i) {
code.push("}")
}
return code.join("\n")
}
//Count the number of compatible inner orders
// This is the length of the longest common prefix of the arrays in orders.
// Each array in orders lists the dimensions of the correspond ndarray in order of increasing stride.
// This is thus the maximum number of dimensions that can be efficiently traversed by simple nested loops for all arrays.
function countMatches(orders) {
var matched = 0, dimension = orders[0].length
while(matched < dimension) {
for(var j=1; j<orders.length; ++j) {
if(orders[j][matched] !== orders[0][matched]) {
return matched
}
}
++matched
}
return matched
}
//Processes a block according to the given data types
// Replaces variable names by different ones, either "local" ones (that are then ferried in and out of the given array) or ones matching the arguments that the function performing the ultimate loop will accept.
function processBlock(block, proc, dtypes) {
var code = block.body
var pre = []
var post = []
for(var i=0; i<block.args.length; ++i) {
var carg = block.args[i]
if(carg.count <= 0) {
continue
}
var re = new RegExp(carg.name, "g")
var ptrStr = ""
var arrNum = proc.arrayArgs.indexOf(i)
switch(proc.argTypes[i]) {
case "offset":
var offArgIndex = proc.offsetArgIndex.indexOf(i)
var offArg = proc.offsetArgs[offArgIndex]
arrNum = offArg.array
ptrStr = "+q" + offArgIndex // Adds offset to the "pointer" in the array
case "array":
ptrStr = "p" + arrNum + ptrStr
var localStr = "l" + i
var arrStr = "a" + arrNum
if (proc.arrayBlockIndices[arrNum] === 0) { // Argument to body is just a single value from this array
if(carg.count === 1) { // Argument/array used only once(?)
if(dtypes[arrNum] === "generic") {
if(carg.lvalue) {
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // Is this necessary if the argument is ONLY used as an lvalue? (keep in mind that we can have a += something, so we would actually need to check carg.rvalue)
code = code.replace(re, localStr)
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
} else {
code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join(""))
}
} else {
code = code.replace(re, [arrStr, "[", ptrStr, "]"].join(""))
}
} else if(dtypes[arrNum] === "generic") {
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // TODO: Could we optimize by checking for carg.rvalue?
code = code.replace(re, localStr)
if(carg.lvalue) {
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
}
} else {
pre.push(["var ", localStr, "=", arrStr, "[", ptrStr, "]"].join("")) // TODO: Could we optimize by checking for carg.rvalue?
code = code.replace(re, localStr)
if(carg.lvalue) {
post.push([arrStr, "[", ptrStr, "]=", localStr].join(""))
}
}
} else { // Argument to body is a "block"
var reStrArr = [carg.name], ptrStrArr = [ptrStr]
for(var j=0; j<Math.abs(proc.arrayBlockIndices[arrNum]); j++) {
reStrArr.push("\\s*\\[([^\\]]+)\\]")
ptrStrArr.push("$" + (j+1) + "*t" + arrNum + "b" + j) // Matched index times stride
}
re = new RegExp(reStrArr.join(""), "g")
ptrStr = ptrStrArr.join("+")
if(dtypes[arrNum] === "generic") {
/*if(carg.lvalue) {
pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // Is this necessary if the argument is ONLY used as an lvalue? (keep in mind that we can have a += something, so we would actually need to check carg.rvalue)
code = code.replace(re, localStr)
post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
} else {
code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join(""))
}*/
throw new Error("cwise: Generic arrays not supported in combination with blocks!")
} else {
// This does not produce any local variables, even if variables are used multiple times. It would be possible to do so, but it would complicate things quite a bit.
code = code.replace(re, [arrStr, "[", ptrStr, "]"].join(""))
}
}
break
case "scalar":
code = code.replace(re, "Y" + proc.scalarArgs.indexOf(i))
break
case "index":
code = code.replace(re, "index")
break
case "shape":
code = code.replace(re, "shape")
break
}
}
return [pre.join("\n"), code, post.join("\n")].join("\n").trim()
}
function typeSummary(dtypes) {
var summary = new Array(dtypes.length)
var allEqual = true
for(var i=0; i<dtypes.length; ++i) {
var t = dtypes[i]
var digits = t.match(/\d+/)
if(!digits) {
digits = ""
} else {
digits = digits[0]
}
if(t.charAt(0) === 0) {
summary[i] = "u" + t.charAt(1) + digits
} else {
summary[i] = t.charAt(0) + digits
}
if(i > 0) {
allEqual = allEqual && summary[i] === summary[i-1]
}
}
if(allEqual) {
return summary[0]
}
return summary.join("")
}
//Generates a cwise operator
function generateCWiseOp(proc, typesig) {
//Compute dimension
// Arrays get put first in typesig, and there are two entries per array (dtype and order), so this gets the number of dimensions in the first array arg.
var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0
var orders = new Array(proc.arrayArgs.length)
var dtypes = new Array(proc.arrayArgs.length)
for(var i=0; i<proc.arrayArgs.length; ++i) {
dtypes[i] = typesig[2*i]
orders[i] = typesig[2*i+1]
}
//Determine where block and loop indices start and end
var blockBegin = [], blockEnd = [] // These indices are exposed as blocks
var loopBegin = [], loopEnd = [] // These indices are iterated over
var loopOrders = [] // orders restricted to the loop indices
for(var i=0; i<proc.arrayArgs.length; ++i) {
if (proc.arrayBlockIndices[i]<0) {
loopBegin.push(0)
loopEnd.push(dimension)
blockBegin.push(dimension)
blockEnd.push(dimension+proc.arrayBlockIndices[i])
} else {
loopBegin.push(proc.arrayBlockIndices[i]) // Non-negative
loopEnd.push(proc.arrayBlockIndices[i]+dimension)
blockBegin.push(0)
blockEnd.push(proc.arrayBlockIndices[i])
}
var newOrder = []
for(var j=0; j<orders[i].length; j++) {
if (loopBegin[i]<=orders[i][j] && orders[i][j]<loopEnd[i]) {
newOrder.push(orders[i][j]-loopBegin[i]) // If this is a loop index, put it in newOrder, subtracting loopBegin, to make sure that all loopOrders are using a common set of indices.
}
}
loopOrders.push(newOrder)
}
//First create arguments for procedure
var arglist = ["SS"] // SS is the overall shape over which we iterate
var code = ["'use strict'"]
var vars = []
for(var j=0; j<dimension; ++j) {
vars.push(["s", j, "=SS[", j, "]"].join("")) // The limits for each dimension.
}
for(var i=0; i<proc.arrayArgs.length; ++i) {
arglist.push("a"+i) // Actual data array
arglist.push("t"+i) // Strides
arglist.push("p"+i) // Offset in the array at which the data starts (also used for iterating over the data)
for(var j=0; j<dimension; ++j) { // Unpack the strides into vars for looping
vars.push(["t",i,"p",j,"=t",i,"[",loopBegin[i]+j,"]"].join(""))
}
for(var j=0; j<Math.abs(proc.arrayBlockIndices[i]); ++j) { // Unpack the strides into vars for block iteration
vars.push(["t",i,"b",j,"=t",i,"[",blockBegin[i]+j,"]"].join(""))
}
}
for(var i=0; i<proc.scalarArgs.length; ++i) {
arglist.push("Y" + i)
}
if(proc.shapeArgs.length > 0) {
vars.push("shape=SS.slice(0)") // Makes the shape over which we iterate available to the user defined functions (so you can use width/height for example)
}
if(proc.indexArgs.length > 0) {
// Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes.
var zeros = new Array(dimension)
for(var i=0; i<dimension; ++i) {
zeros[i] = "0"
}
vars.push(["index=[", zeros.join(","), "]"].join(""))
}
for(var i=0; i<proc.offsetArgs.length; ++i) { // Offset arguments used for stencil operations
var off_arg = proc.offsetArgs[i]
var init_string = []
for(var j=0; j<off_arg.offset.length; ++j) {
if(off_arg.offset[j] === 0) {
continue
} else if(off_arg.offset[j] === 1) {
init_string.push(["t", off_arg.array, "p", j].join(""))
} else {
init_string.push([off_arg.offset[j], "*t", off_arg.array, "p", j].join(""))
}
}
if(init_string.length === 0) {
vars.push("q" + i + "=0")
} else {
vars.push(["q", i, "=", init_string.join("+")].join(""))
}
}
//Prepare this variables
var thisVars = uniq([].concat(proc.pre.thisVars)
.concat(proc.body.thisVars)
.concat(proc.post.thisVars))
vars = vars.concat(thisVars)
code.push("var " + vars.join(","))
for(var i=0; i<proc.arrayArgs.length; ++i) {
code.push("p"+i+"|=0")
}
//Inline prelude
if(proc.pre.body.length > 3) {
code.push(processBlock(proc.pre, proc, dtypes))
}
//Process body
var body = processBlock(proc.body, proc, dtypes)
var matched = countMatches(loopOrders)
if(matched < dimension) {
code.push(outerFill(matched, loopOrders[0], proc, body)) // TODO: Rather than passing loopOrders[0], it might be interesting to look at passing an order that represents the majority of the arguments for example.
} else {
code.push(innerFill(loopOrders[0], proc, body))
}
//Inline epilog
if(proc.post.body.length > 3) {
code.push(processBlock(proc.post, proc, dtypes))
}
if(proc.debug) {
console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------")
}
var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("")
var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join(""))
return f()
}
module.exports = generateCWiseOp
},{"uniq":22}],7:[function(require,module,exports){
"use strict"
// The function below is called when constructing a cwise function object, and does the following:
// A function object is constructed which accepts as argument a compilation function and returns another function.
// It is this other function that is eventually returned by createThunk, and this function is the one that actually
// checks whether a certain pattern of arguments has already been used before and compiles new loops as needed.
// The compilation passed to the first function object is used for compiling new functions.
// Once this function object is created, it is called with compile as argument, where the first argument of compile
// is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise).
// So createThunk roughly works like this:
// function createThunk(proc) {
// var thunk = function(compileBound) {
// var CACHED = {}
// return function(arrays and scalars) {
// if (dtype and order of arrays in CACHED) {
// var func = CACHED[dtype and order of arrays]
// } else {
// var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays)
// }
// return func(arrays and scalars)
// }
// }
// return thunk(compile.bind1(proc))
// }
var compile = require("./compile.js")
function createThunk(proc) {
var code = ["'use strict'", "var CACHED={}"]
var vars = []
var thunkName = proc.funcName + "_cwise_thunk"
//Build thunk
code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join(""))
var typesig = []
var string_typesig = []
var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS).
Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")]
var shapeLengthConditions = [], shapeConditions = []
// Process array arguments
for(var i=0; i<proc.arrayArgs.length; ++i) {
var j = proc.arrayArgs[i]
vars.push(["t", j, "=array", j, ".dtype,",
"r", j, "=array", j, ".order"].join(""))
typesig.push("t" + j)
typesig.push("r" + j)
string_typesig.push("t"+j)
string_typesig.push("r"+j+".join()")
proc_args.push("array" + j + ".data")
proc_args.push("array" + j + ".stride")
proc_args.push("array" + j + ".offset|0")
if (i>0) { // Gather conditions to check for shape equality (ignoring block indices)
shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i])))
shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]")
}
}
// Check for shape equality
if (proc.arrayArgs.length > 1) {
code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')")
code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {")
code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')")
code.push("}")
}
// Process scalar arguments
for(var i=0; i<proc.scalarArgs.length; ++i) {
proc_args.push("scalar" + proc.scalarArgs[i])
}
// Check for cached function (and if not present, generate it)
vars.push(["type=[", string_typesig.join(","), "].join()"].join(""))
vars.push("proc=CACHED[type]")
code.push("var " + vars.join(","))
code.push(["if(!proc){",
"CACHED[type]=proc=compile([", typesig.join(","), "])}",
"return proc(", proc_args.join(","), ")}"].join(""))
if(proc.debug) {
console.log("-----Generated thunk:\n" + code.join("\n") + "\n----------")
}
//Compile thunk
var thunk = new Function("compile", code.join("\n"))
return thunk(compile.bind(undefined, proc))
}
module.exports = createThunk
},{"./compile.js":6}],8:[function(require,module,exports){
module.exports = require("cwise-compiler")
},{"cwise-compiler":5}],9:[function(require,module,exports){
"use strict"
function dupe_array(count, value, i) {
var c = count[i]|0
if(c <= 0) {
return []
}
var result = new Array(c), j
if(i === count.length-1) {
for(j=0; j<c; ++j) {
result[j] = value
}
} else {
for(j=0; j<c; ++j) {
result[j] = dupe_array(count, value, i+1)
}
}
return result
}
function dupe_number(count, value) {
var result, i
result = new Array(count)
for(i=0; i<count; ++i) {
result[i] = value
}
return result
}
function dupe(count, value) {
if(typeof value === "undefined") {
value = 0
}
switch(typeof count) {
case "number":
if(count > 0) {
return dupe_number(count|0, value)
}
break
case "object":
if(typeof (count.length) === "number") {
return dupe_array(count, value, 0)
}
break
}
return []
}
module.exports = dupe
},{}],10:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
var e, m
var eLen = nBytes * 8 - mLen - 1
var eMax = (1 << eLen) - 1
var eBias = eMax >> 1
var nBits = -7
var i = isLE ? (nBytes - 1) : 0
var d = isLE ? -1 : 1
var 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.write = function (buffer, value, offset, isLE, mLen, nBytes) {
var e, m, c
var eLen = nBytes * 8 - mLen - 1
var eMax = (1 << eLen) - 1
var eBias = eMax >> 1
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
var i = isLE ? 0 : (nBytes - 1)
var d = isLE ? 1 : -1
var 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
}
},{}],11:[function(require,module,exports){
"use strict"
function iota(n) {
var result = new Array(n)
for(var i=0; i<n; ++i) {
result[i] = i
}
return result
}
module.exports = iota
},{}],12:[function(require,module,exports){
/*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
// The _isBuffer check is for Safari 5-7 support, because it's missing
// Object.prototype.constructor. Remove this eventually
module.exports = function (obj) {
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
}
function isBuffer (obj) {
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
}
// For Node v0.10 support. Remove this eventually.
function isSlowBuffer (obj) {
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
}
},{}],13:[function(require,module,exports){
'use strict'
var ops = require('ndarray-ops')
var ndarray = require('ndarray')
var pool = require('typedarray-pool')
var fftm = require('./lib/fft-matrix.js')
function ndfft(dir, x, y) {
var shape = x.shape
, d = shape.length
, size = 1
, stride = new Array(d)
, pad = 0
, i, j
for(i=d-1; i>=0; --i) {
stride[i] = size
size *= shape[i]
pad = Math.max(pad, fftm.scratchMemory(shape[i]))
if(x.shape[i] !== y.shape[i]) {
throw new Error('Shape mismatch, real and imaginary arrays must have same size')
}
}
var buf_size = 4 * size + pad
var buffer
if( x.dtype === 'array' ||
x.dtype === 'float64' ||
x.dtype === 'custom' ) {
buffer = pool.mallocDouble(buf_size)
} else {
buffer = pool.mallocFloat(buf_size)
}
var x1 = ndarray(buffer, shape.slice(0), stride, 0)
, y1 = ndarray(buffer, shape.slice(0), stride.slice(0), size)
, x2 = ndarray(buffer, shape.slice(0), stride.slice(0), 2*size)
, y2 = ndarray(buffer, shape.slice(0), stride.slice(0), 3*size)
, tmp, n, s1, s2
, scratch_ptr = 4 * size
//Copy into x1/y1
ops.assign(x1, x)
ops.assign(y1, y)
for(i=d-1; i>=0; --i) {
fftm(dir, size/shape[i], shape[i], buffer, x1.offset, y1.offset, scratch_ptr)
if(i === 0) {
break
}
//Compute new stride for x2/y2
n = 1
s1 = x2.stride
s2 = y2.stride
for(j=i-1; j<d; ++j) {
s2[j] = s1[j] = n
n *= shape[j]
}
for(j=i-2; j>=0; --j) {
s2[j] = s1[j] = n
n *= shape[j]
}
//Transpose
ops.assign(x2, x1)
ops.assign(y2, y1)
//Swap buffers
tmp = x1
x1 = x2
x2 = tmp
tmp = y1
y1 = y2
y2 = tmp
}
//Copy result back into x
ops.assign(x, x1)
ops.assign(y, y1)
pool.free(buffer)
}
module.exports = ndfft
},{"./lib/fft-matrix.js":14,"ndarray":18,"ndarray-ops":17,"typedarray-pool":21}],14:[function(require,module,exports){
var bits = require('bit-twiddle')
function fft(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr) {
dir |= 0
nrows |= 0
ncols |= 0
x_ptr |= 0
y_ptr |= 0
if(bits.isPow2(ncols)) {
fftRadix2(dir, nrows, ncols, buffer, x_ptr, y_ptr)
} else {
fftBluestein(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr)
}
}
module.exports = fft
function scratchMemory(n) {
if(bits.isPow2(n)) {
return 0
}
return 2 * n + 4 * bits.nextPow2(2*n + 1)
}
module.exports.scratchMemory = scratchMemory
//Radix 2 FFT Adapted from Paul Bourke's C Implementation
function fftRadix2(dir, nrows, ncols, buffer, x_ptr, y_ptr) {
dir |= 0
nrows |= 0
ncols |= 0
x_ptr |= 0
y_ptr |= 0
var nn,m,i,i1,j,k,i2,l,l1,l2
var c1,c2,t,t1,t2,u1,u2,z,row,a,b,c,d,k1,k2,k3
// Calculate the number of points
nn = ncols
m = bits.log2(nn)
for(row=0; row<nrows; ++row) {
// Do the bit reversal
i2 = nn >> 1;
j = 0;
for(i=0;i<nn-1;i++) {
if(i < j) {
t = buffer[x_ptr+i]
buffer[x_ptr+i] = buffer[x_ptr+j]
buffer[x_ptr+j] = t
t = buffer[y_ptr+i]
buffer[y_ptr+i] = buffer[y_ptr+j]
buffer[y_ptr+j] = t
}
k = i2
while(k <= j) {
j -= k
k >>= 1
}
j += k
}
// Compute the FFT
c1 = -1.0
c2 = 0.0
l2 = 1
for(l=0;l<m;l++) {
l1 = l2
l2 <<= 1
u1 = 1.0
u2 = 0.0
for(j=0;j<l1;j++) {
for(i=j;i<nn;i+=l2) {
i1 = i + l1
a = buffer[x_ptr+i1]
b = buffer[y_ptr+i1]
c = buffer[x_ptr+i]
d = buffer[y_ptr+i]
k1 = u1 * (a + b)
k2 = a * (u2 - u1)
k3 = b * (u1 + u2)
t1 = k1 - k3
t2 = k1 + k2
buffer[x_ptr+i1] = c - t1
buffer[y_ptr+i1] = d - t2
buffer[x_ptr+i] += t1
buffer[y_ptr+i] += t2
}
k1 = c1 * (u1 + u2)
k2 = u1 * (c2 - c1)
k3 = u2 * (c1 + c2)
u1 = k1 - k3
u2 = k1 + k2
}
c2 = Math.sqrt((1.0 - c1) / 2.0)
if(dir < 0) {
c2 = -c2
}
c1 = Math.sqrt((1.0 + c1) / 2.0)
}
// Scaling for inverse transform
if(dir < 0) {
var scale_f = 1.0 / nn
for(i=0;i<nn;i++) {
buffer[x_ptr+i] *= scale_f
buffer[y_ptr+i] *= scale_f
}
}
// Advance pointers
x_ptr += ncols
y_ptr += ncols
}
}
// Use Bluestein algorithm for npot FFTs
// Scratch memory required: 2 * ncols + 4 * bits.nextPow2(2*ncols + 1)
function fftBluestein(dir, nrows, ncols, buffer, x_ptr, y_ptr, scratch_ptr) {
dir |= 0
nrows |= 0
ncols |= 0
x_ptr |= 0
y_ptr |= 0
scratch_ptr |= 0
// Initialize tables
var m = bits.nextPow2(2 * ncols + 1)
, cos_ptr = scratch_ptr
, sin_ptr = cos_ptr + ncols
, xs_ptr = sin_ptr + ncols
, ys_ptr = xs_ptr + m
, cft_ptr = ys_ptr + m
, sft_ptr = cft_ptr + m
, w = -dir * Math.PI / ncols
, row, a, b, c, d, k1, k2, k3
, i
for(i=0; i<ncols; ++i) {
a = w * ((i * i) % (ncols * 2))
c = Math.cos(a)
d = Math.sin(a)
buffer[cft_ptr+(m-i)] = buffer[cft_ptr+i] = buffer[cos_ptr+i] = c
buffer[sft_ptr+(m-i)] = buffer[sft_ptr+i] = buffer[sin_ptr+i] = d
}
for(i=ncols; i<=m-ncols; ++i) {
buffer[cft_ptr+i] = 0.0
}
for(i=ncols; i<=m-ncols; ++i) {
buffer[sft_ptr+i] = 0.0
}
fftRadix2(1, 1, m, buffer, cft_ptr, sft_ptr)
//Compute scale factor
if(dir < 0) {
w = 1.0 / ncols
} else {
w = 1.0
}
//Handle direction
for(row=0; row<nrows; ++row) {
// Copy row into scratch memory, multiply weights
for(i=0; i<ncols; ++i) {
a = buffer[x_ptr+i]
b = buffer[y_ptr+i]
c = buffer[cos_ptr+i]
d = -buffer[sin_ptr+i]
k1 = c * (a + b)
k2 = a * (d - c)
k3 = b * (c + d)
buffer[xs_ptr+i] = k1 - k3
buffer[ys_ptr+i] = k1 + k2
}
//Zero out the rest
for(i=ncols; i<m; ++i) {
buffer[xs_ptr+i] = 0.0
}
for(i=ncols; i<m; ++i) {
buffer[ys_ptr+i] = 0.0
}
// FFT buffer
fftRadix2(1, 1, m, buffer, xs_ptr, ys_ptr)
// Apply multiplier
for(i=0; i<m; ++i) {
a = buffer[xs_ptr+i]
b = buffer[ys_ptr+i]
c = buffer[cft_ptr+i]
d = buffer[sft_ptr+i]
k1 = c * (a + b)
k2 = a * (d - c)
k3 = b * (c + d)
buffer[xs_ptr+i] = k1 - k3
buffer[ys_ptr+i] = k1 + k2
}
// Inverse FFT buffer
fftRadix2(-1, 1, m, buffer, xs_ptr, ys_ptr)
// Copy result back into x/y
for(i=0; i<ncols; ++i) {
a = buffer[xs_ptr+i]
b = buffer[ys_ptr+i]
c = buffer[cos_ptr+i]
d = -buffer[sin_ptr+i]
k1 = c * (a + b)
k2 = a * (d - c)
k3 = b * (c + d)
buffer[x_ptr+i] = w * (k1 - k3)
buffer[y_ptr+i] = w * (k1 + k2)
}
x_ptr += ncols
y_ptr += ncols
}
}
},{"bit-twiddle":2}],15:[function(require,module,exports){
"use strict"
module.exports = matrixProduct
var generatePlan = require("./lib/planner.js")
function shape(arr) {
if(Array.isArray(arr)) {
return [ arr.length, arr[0].length ]
} else {
return arr.shape
}
}
function checkShapes(out, a, b) {
var os = shape(out)
var as = shape(a)
var bs = shape(b)
if(os[0] !== as[0] || os[1] !== bs[1] || as[1] !== bs[0]) {
throw new Error("Mismatched array shapes for matrix product")
}
}
function classifyType(m) {
if(Array.isArray(m)) {
if(Array.isArray(m)) {
return [ "r", "native" ]
}
} else if(m.shape && (m.shape.length === 2)) {
if(m.order[0]) {
return [ "r", m.dtype ]
} else {
return [ "c", m.dtype ]
}
}
throw new Error("Unrecognized data type")
}
var CACHE = {}
function matrixProduct(out, a, b, alpha, beta) {
if(alpha === undefined) {
alpha = 1.0
}
if(beta === undefined) {
beta = 0.0
}
var useAlpha = (alpha !== 1.0)
var useBeta = (beta !== 0.0)
var outType = classifyType(out)
var aType = classifyType(a)
var bType = classifyType(b)
checkShapes(out, a, b)
var typeSig = [ outType, aType, bType, useAlpha, useBeta ].join(":")
var proc = CACHE[typeSig]
if(!proc) {
proc = CACHE[typeSig] = generatePlan(outType, aType, bType, useAlpha, useBeta)
}
return proc(out, a, b, alpha, beta)
}
},{"./lib/planner.js":16}],16:[function(require,module,exports){
"use strict"
module.exports = generateMatrixProduct
var BLOCK_SIZE = 32
function unpackOrder(order) {
return order === "r" ? [1,0] : [0,1]
}
function unpackShape(name, type) {
if(type[1] === "native") {
return [
name, "d0=", name, ".length,",
name, "d1=", name, "[0].length,"
].join("")
} else {
return [
name, "d0=", name, ".shape[0],",
name, "d1=", name, ".shape[1],",
name, "s0=", name, ".stride[0],",
name, "s1=", name, ".stride[1],",
name, "o=", name, ".offset,",
name, "d=", name, ".data,"
].join("")
}
}
function start(order, name, type, i, j, w) {
var code = []
if(type[1] === "native") {
if(order[0]) {
if(i) {
code.push("var ", name, "p=", name, "[", i, "];")
} else {
code.push("var ", name, "p=", name, "[0];")
}
}
} else {
if(i && j) {
if(w) {
code.push(
"var ", name, "t0=", name, "s", order[0], ",",
name, "t1=", name, "s", order[1], "-", name, "s", order[0], "*", w, ",",
name, "p=", name, "o+", i, "*", name, "s0+", j, "*", name, "s1;")
} else {
code.push(
"var ", name, "t0=", name, "s", order[0], ",",
name, "p=", name, "o+", i, "*", name, "s0+", j, "*", name, "s1;")
}
} else if(i) {
code.push(
"var ", name, "t0=", name, "s", order[0], ",",
name, "p=", name, "o+", i, "*", name, "s0;")
} else if(j) {
code.push(
"var ", name, "t0=", name, "s", order[0], ",",
name, "p=", name, "o+", j, "*", name, "s1;")
} else {
code.push(
"var ", name, "t0=", name, "s", order[0], ",",
name, "t1=", name, "s", order[1], "-", name, "s", order[0], "*", name, "d", order[0], ",",
name, "p=", name, "o;")
}
}
return code
}
function walk(order, name, type, d, i) {
var code = []
if(type[1] === "native") {
if(order[0] && d === 1) {
code.push(name, "p=", name, "[", i, "+1]")
}
} else {
code.push(name, "p+=", name, "t", d, ";")
}
return code
}
function write(order, name, type, i, j, w) {
var code = []
if(type[1] === "native") {
if(order[0]) {
code.push(name, "p[", j, "]=", w, ";")
} else {
code.push(name, "[", i, "][", j, "]=", w, ";")
}
} else if(type[1] === "generic") {
code.push(name, "d.set(", name, "p,", w, ");")
} else {
code.push(name, "d[", name, "p]=", w, ";")
}
return code
}
function read(order, name, type, i, j) {
var code = []
if(type[1] === "native") {
if(order[0]) {
code.push(name, "p[", j, "]")
} else {
code.push(name, "[", i, "][", j, "]")
}
} else if(type[1] === "generic") {
code.push(name, "d.get(", name, "p)")
} else {
code.push(name, "d[", name, "p]")
}
return code.join("")
}
function generateRowColumnLoop(oType, aType, bType, useAlpha, useBeta) {
var code = []
var oOrd = oType[0] === "r" ? [1,0] : [0,1], aOrd = [1, 0], bOrd = [0, 1]
var symbols = ["i", "j"]
code.push.apply(code, start(oOrd, "o", oType))
if(oOrd[1]) {
code.push("for(j=0;j<od1;++j){")
code.push("for(i=0;i<od0;++i){")
} else {
code.push("for(i=0;i<od0;++i){")
code.push("for(j=0;j<od1;++j){")
}
code.push.apply(code, start(aOrd, "a", aType, "i"))
code.push.apply(code, start(bOrd, "b", bType, undefined, "j"))
code.push(
"var r=0.0;",
"for(k=0;k<ad1;++k){",
"r+=",
read(aOrd, "a", aType, "i", "k"), "*",
read(bOrd, "b", bType, "k", "j"), ";")
//Terminate k loop
code.push.apply(code, walk(aOrd, "a", aType, 0, "k"))
code.push.apply(code, walk(bOrd, "b", bType, 0, "k"))
code.push("}")
//Write r to output
if(useAlpha) {
code.push("r*=A;")
}
if(useBeta) {
code.push("r+=B*", read(oOrd, "o", oType, "i", "j"), ";")
}
code.push.apply(code, write(oOrd, "o", oType, "i", "j", "r"))
//Terminate j loop loop
code.push.apply(code, walk(oOrd, "o", oType, 0, symbols[1]))
code.push("}")
//Terminate i loop
code.push.apply(code, walk(oOrd, "o", oType, 1, symbols[0]))
code.push("}")
return code
}
function generateBetaPass(oType, useBeta) {
var code = []
var oOrd = oType[0] === "r" ? [1,0] : [0,1], symbols
if(useBeta) {
code.push("if(B!==1.0){")
}
code.push.apply(code, start(oOrd, "o", oType))
if(oOrd[0]) {
code.push("for(i=0;i<od0;++i){for(j=0;j<od1;++j){")
symbols = ["i", "j"]
} else {
code.push("for(j=0;j<od1;++j){for(i=0;i<od0;++i){")
symbols = ["j", "i"]
}
if(useBeta) {
code.push.apply(code, write(oOrd, "o", oType, "i", "j",
"B*"+read(oOrd, "o", oType, "i", "j")))
} else {
code.push.apply(code, write(oOrd, "o", oType, "i", "j", "0"))
}
code.push.apply(code, walk(oOrd, "o", oType, 0, symbols[1]))
code.push("}")
code.push.apply(code, walk(oOrd, "o", oType, 1, symbols[0]))
code.push("}")
if(useBeta) {
code.push("}")
}
return code
}
function generateBlockLoop(oType, aType, bType, useAlpha, useBeta) {
var code = []
var shapes = [ "od0", "od1", "ad1" ]
var oOrd = [1, 0]
var aOrd = [1, 0]
var bOrd = [0, 1]
//Do pass over output to zero it out
code.push.apply(code, generateBetaPass(oType, useBeta))
for(var i=0; i<3; ++i) {
code.push(
"for(var i", i, "=", shapes[i], ";i", i, ">0;){",
"var w", i, "=", BLOCK_SIZE, ";",
"if(i", i, "<", BLOCK_SIZE, "){",
"w", i, "=i", i, ";",
"i", i, "=0;",
"}else{",
"i", i, "-=", BLOCK_SIZE, ";",
"}")
}
code.push.apply(code, start(oOrd, "o", oType, "i0", "i1", "w1"))
code.push("for(i=0;i<w0;++i){\
for(j=0;j<w1;++j){\
var r=0.0;")
code.push.apply(code, start(aOrd, "a", aType, "(i0+i)", "i2"))
code.push.apply(code, start(bOrd, "b", bType, "i2", "(i1+j)"))
code.push("for(k=0;k<w2;++k){")
code.push("r+=",
read(aOrd, "a", aType, "(i0+i)", "(i2+k)"), "*",
read(bOrd, "b", bType, "(i2+k)", "(i1+j)"), ";")
//Close off k-loop
code.push.apply(code, walk(aOrd, "a", aType, 0, "(i2+k)"))
code.push.apply(code, walk(bOrd, "b", bType, 0, "(i2+k)"))
code.push("}")
//Write r back to output array
var sym = "r"
if(useAlpha) {
sym = "A*r"
}
code.push.apply(code, write(oOrd, "o", oType, "(i0+i)", "(i1+j)",
sym + "+" + read(oOrd, "o", oType, "(i0+i)", "(i1+j)")))
//Close off j-loop
code.push.apply(code, walk(oOrd, "o", oType, 0, "(i1+j)"))
code.push("}")
//Close off i-loop
code.push.apply(code, walk(oOrd, "o", oType, 1, "(i0+i)"))
code.push("}}}}")
return code
}
function generateMatrixProduct(outType, aType, bType, useAlpha, useBeta) {
var funcName = ["gemm", outType[0], outType[1],
"a", aType[0], aType[1],
"b", bType[0], bType[1],
useAlpha ? "alpha" : "",
useBeta ? "beta" : "" ].join("")
var code = [
"function ", funcName, "(o,a,b,A,B){",
"var ", unpackShape("o", outType),
unpackShape("a", aType),
unpackShape("b", bType),
"i,j,k;"
]
if(aType[0] === "r" && bType[0] === "c") {
code.push.apply(code, generateRowColumnLoop(outType, aType, bType, useAlpha, useBeta))
} else {
code.push.apply(code, generateBlockLoop(outType, aType, bType, useAlpha, useBeta))
}
code.push("}return ", funcName)
//Compile function
var proc = new Function(code.join(""))
return proc()
}
},{}],17:[function(require,module,exports){
"use strict"
var compile = require("cwise-compiler")
var EmptyProc = {
body: "",
args: [],
thisVars: [],
localVars: []
}
function fixup(x) {
if(!x) {
return EmptyProc
}
for(var i=0; i<x.args.length; ++i) {
var a = x.args[i]
if(i === 0) {
x.args[i] = {name: a, lvalue:true, rvalue: !!x.rvalue, count:x.count||1 }
} else {
x.args[i] = {name: a, lvalue:false, rvalue:true, count: 1}
}
}
if(!x.thisVars) {
x.thisVars = []
}
if(!x.localVars) {
x.localVars = []
}
return x
}
function pcompile(user_args) {
return compile({
args: user_args.args,
pre: fixup(user_args.pre),
body: fixup(user_args.body),
post: fixup(user_args.proc),
funcName: user_args.funcName
})
}
function makeOp(user_args) {
var args = []
for(var i=0; i<user_args.args.length; ++i) {
args.push("a"+i)
}
var wrapper = new Function("P", [
"return function ", user_args.funcName, "_ndarrayops(", args.join(","), ") {P(", args.join(","), ");return a0}"
].join(""))
return wrapper(pcompile(user_args))
}
var assign_ops = {
add: "+",
sub: "-",
mul: "*",
div: "/",
mod: "%",
band: "&",
bor: "|",
bxor: "^",
lshift: "<<",
rshift: ">>",
rrshift: ">>>"
}
;(function(){
for(var id in assign_ops) {
var op = assign_ops[id]
exports[id] = makeOp({
args: ["array","array","array"],
body: {args:["a","b","c"],
body: "a=b"+op+"c"},
funcName: id
})
exports[id+"eq"] = makeOp({
args: ["array","array"],
body: {args:["a","b"],
body:"a"+op+"=b"},
rvalue: true,
funcName: id+"eq"
})
exports[id+"s"] = makeOp({
args: ["array", "array", "scalar"],
body: {args:["a","b","s"],
body:"a=b"+op+"s"},
funcName: id+"s"
})
exports[id+"seq"] = makeOp({
args: ["array","scalar"],
body: {args:["a","s"],
body:"a"+op+"=s"},
rvalue: true,
funcName: id+"seq"
})
}
})();
var unary_ops = {
not: "!",
bnot: "~",
neg: "-",
recip: "1.0/"
}
;(function(){
for(var id in unary_ops) {
var op = unary_ops[id]
exports[id] = makeOp({
args: ["array", "array"],
body: {args:["a","b"],
body:"a="+op+"b"},
funcName: id
})
exports[id+"eq"] = makeOp({
args: ["array"],
body: {args:["a"],
body:"a="+op+"a"},
rvalue: true,
count: 2,
funcName: id+"eq"
})
}
})();
var binary_ops = {
and: "&&",
or: "||",
eq: "===",
neq: "!==",
lt: "<",
gt: ">",
leq: "<=",
geq: ">="
}
;(function() {
for(var id in binary_ops) {
var op = binary_ops[id]
exports[id] = makeOp({
args: ["array","array","array"],
body: {args:["a", "b", "c"],
body:"a=b"+op+"c"},
funcName: id
})
exports[id+"s"] = makeOp({
args: ["array","array","scalar"],
body: {args:["a", "b", "s"],
body:"a=b"+op+"s"},
funcName: id+"s"
})
exports[id+"eq"] = makeOp({
args: ["array", "array"],
body: {args:["a", "b"],
body:"a=a"+op+"b"},
rvalue:true,
count:2,
funcName: id+"eq"
})
exports[id+"seq"] = makeOp({
args: ["array", "scalar"],
body: {args:["a","s"],
body:"a=a"+op+"s"},
rvalue:true,
count:2,
funcName: id+"seq"
})
}
})();
var math_unary = [
"abs",
"acos",
"asin",
"atan",
"ceil",
"cos",
"exp",
"floor",
"log",
"round",
"sin",
"sqrt",
"tan"
]
;(function() {
for(var i=0; i<math_unary.length; ++i) {
var f = math_unary[i]
exports[f] = makeOp({
args: ["array", "array"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b"], body:"a=this_f(b)", thisVars:["this_f"]},
funcName: f
})
exports[f+"eq"] = makeOp({
args: ["array"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args: ["a"], body:"a=this_f(a)", thisVars:["this_f"]},
rvalue: true,
count: 2,
funcName: f+"eq"
})
}
})();
var math_comm = [
"max",
"min",
"atan2",
"pow"
]
;(function(){
for(var i=0; i<math_comm.length; ++i) {
var f= math_comm[i]
exports[f] = makeOp({
args:["array", "array", "array"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b","c"], body:"a=this_f(b,c)", thisVars:["this_f"]},
funcName: f
})
exports[f+"s"] = makeOp({
args:["array", "array", "scalar"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b","c"], body:"a=this_f(b,c)", thisVars:["this_f"]},
funcName: f+"s"
})
exports[f+"eq"] = makeOp({ args:["array", "array"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b"], body:"a=this_f(a,b)", thisVars:["this_f"]},
rvalue: true,
count: 2,
funcName: f+"eq"
})
exports[f+"seq"] = makeOp({ args:["array", "scalar"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b"], body:"a=this_f(a,b)", thisVars:["this_f"]},
rvalue:true,
count:2,
funcName: f+"seq"
})
}
})();
var math_noncomm = [
"atan2",
"pow"
]
;(function(){
for(var i=0; i<math_noncomm.length; ++i) {
var f= math_noncomm[i]
exports[f+"op"] = makeOp({
args:["array", "array", "array"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b","c"], body:"a=this_f(c,b)", thisVars:["this_f"]},
funcName: f+"op"
})
exports[f+"ops"] = makeOp({
args:["array", "array", "scalar"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b","c"], body:"a=this_f(c,b)", thisVars:["this_f"]},
funcName: f+"ops"
})
exports[f+"opeq"] = makeOp({ args:["array", "array"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b"], body:"a=this_f(b,a)", thisVars:["this_f"]},
rvalue: true,
count: 2,
funcName: f+"opeq"
})
exports[f+"opseq"] = makeOp({ args:["array", "scalar"],
pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
body: {args:["a","b"], body:"a=this_f(b,a)", thisVars:["this_f"]},
rvalue:true,
count:2,
funcName: f+"opseq"
})
}
})();
exports.any = compile({
args:["array"],
pre: EmptyProc,
body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "if(a){return true}", localVars: [], thisVars: []},
post: {args:[], localVars:[], thisVars:[], body:"return false"},
funcName: "any"
})
exports.all = compile({
args:["array"],
pre: EmptyProc,
body: {args:[{name:"x", lvalue:false, rvalue:true, count:1}], body: "if(!x){return false}", localVars: [], thisVars: []},
post: {args:[], localVars:[], thisVars:[], body:"return true"},
funcName: "all"
})
exports.sum = compile({
args:["array"],
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "this_s+=a", localVars: [], thisVars: ["this_s"]},
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
funcName: "sum"
})
exports.prod = compile({
args:["array"],
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=1"},
body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "this_s*=a", localVars: [], thisVars: ["this_s"]},
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
funcName: "prod"
})
exports.norm2squared = compile({
args:["array"],
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
body: {args:[{name:"a", lvalue:false, rvalue:true, count:2}], body: "this_s+=a*a", localVars: [], thisVars: ["this_s"]},
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
funcName: "norm2squared"
})
exports.norm2 = compile({
args:["array"],
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
body: {args:[{name:"a", lvalue:false, rvalue:true, count:2}], body: "this_s+=a*a", localVars: [], thisVars: ["this_s"]},
post: {args:[], localVars:[], thisVars:["this_s"], body:"return Math.sqrt(this_s)"},
funcName: "norm2"
})
exports.norminf = compile({
args:["array"],
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
body: {args:[{name:"a", lvalue:false, rvalue:true, count:4}], body:"if(-a>this_s){this_s=-a}else if(a>this_s){this_s=a}", localVars: [], thisVars: ["this_s"]},
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
funcName: "norminf"
})
exports.norm1 = compile({
args:["array"],
pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
body: {args:[{name:"a", lvalue:false, rvalue:true, count:3}], body: "this_s+=a<0?-a:a", localVars: [], thisVars: ["this_s"]},
post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
funcName: "norm1"
})
exports.sup = compile({
args: [ "array" ],
pre:
{ body: "this_h=-Infinity",
args: [],
thisVars: [ "this_h" ],
localVars: [] },
body:
{ body: "if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_",
args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ],
thisVars: [ "this_h" ],
localVars: [] },
post:
{ body: "return this_h",
args: [],
thisVars: [ "this_h" ],
localVars: [] }
})
exports.inf = compile({
args: [ "array" ],
pre:
{ body: "this_h=Infinity",
args: [],
thisVars: [ "this_h" ],
localVars: [] },
body:
{ body: "if(_inline_1_arg0_<this_h)this_h=_inline_1_arg0_",
args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ],
thisVars: [ "this_h" ],
localVars: [] },
post:
{ body: "return this_h",
args: [],
thisVars: [ "this_h" ],
localVars: [] }
})
exports.argmin = compile({
args:["index","array","shape"],
pre:{
body:"{this_v=Infinity;this_i=_inline_0_arg2_.slice(0)}",
args:[
{name:"_inline_0_arg0_",lvalue:false,rvalue:false,count:0},
{name:"_inline_0_arg1_",lvalue:false,rvalue:false,count:0},
{name:"_inline_0_arg2_",lvalue:false,rvalue:true,count:1}
],
thisVars:["this_i","this_v"],
localVars:[]},
body:{
body:"{if(_inline_1_arg1_<this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",
args:[
{name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2},
{name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}],
thisVars:["this_i","this_v"],
localVars:["_inline_1_k"]},
post:{
body:"{return this_i}",
args:[],
thisVars:["this_i"],
localVars:[]}
})
exports.argmax = compile({
args:["index","array","shape"],
pre:{
body:"{this_v=-Infinity;this_i=_inline_0_arg2_.slice(0)}",
args:[
{name:"_inline_0_arg0_",lvalue:false,rvalue:false,count:0},
{name:"_inline_0_arg1_",lvalue:false,rvalue:false,count:0},
{name:"_inline_0_arg2_",lvalue:false,rvalue:true,count:1}
],
thisVars:["this_i","this_v"],
localVars:[]},
body:{
body:"{if(_inline_1_arg1_>this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",
args:[
{name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2},
{name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}],
thisVars:["this_i","this_v"],
localVars:["_inline_1_k"]},
post:{
body:"{return this_i}",
args:[],
thisVars:["this_i"],
localVars:[]}
})
exports.random = makeOp({
args: ["array"],
pre: {args:[], body:"this_f=Math.random", thisVars:["this_f"]},
body: {args: ["a"], body:"a=this_f()", thisVars:["this_f"]},
funcName: "random"
})
exports.assign = makeOp({
args:["array", "array"],
body: {args:["a", "b"], body:"a=b"},
funcName: "assign" })
exports.assigns = makeOp({
args:["array", "scalar"],
body: {args:["a", "b"], body:"a=b"},
funcName: "assigns" })
exports.equals = compile({
args:["array", "array"],
pre: EmptyProc,
body: {args:[{name:"x", lvalue:false, rvalue:true, count:1},
{name:"y", lvalue:false, rvalue:true, count:1}],
body: "if(x!==y){return false}",
localVars: [],
thisVars: []},
post: {args:[], localVars:[], thisVars:[], body:"return true"},
funcName: "equals"
})
},{"cwise-compiler":5}],18:[function(require,module,exports){
var iota = require("iota-array")
var isBuffer = require("is-buffer")
var hasTypedArrays = ((typeof Float64Array) !== "undefined")
function compare1st(a, b) {
return a[0] - b[0]
}
function order() {
var stride = this.stride
var terms = new Array(stride.length)
var i
for(i=0; i<terms.length; ++i) {
terms[i] = [Math.abs(stride[i]), i]
}
terms.sort(compare1st)
var result = new Array(terms.length)
for(i=0; i<result.length; ++i) {
result[i] = terms[i][1]
}
return result
}
function compileConstructor(dtype, dimension) {
var className = ["View", dimension, "d", dtype].join("")
if(dimension < 0) {
className = "View_Nil" + dtype
}
var useGetters = (dtype === "generic")
if(dimension === -1) {
//Special case for trivial arrays
var code =
"function "+className+"(a){this.data=a;};\
var proto="+className+".prototype;\
proto.dtype='"+dtype+"';\
proto.index=function(){return -1};\
proto.size=0;\
proto.dimension=-1;\
proto.shape=proto.stride=proto.order=[];\
proto.lo=proto.hi=proto.transpose=proto.step=\
function(){return new "+className+"(this.data);};\
proto.get=proto.set=function(){};\
proto.pick=function(){return null};\
return function construct_"+className+"(a){return new "+className+"(a);}"
var procedure = new Function(code)
return procedure()
} else if(dimension === 0) {
//Special case for 0d arrays
var code =
"function "+className+"(a,d) {\
this.data = a;\
this.offset = d\
};\
var proto="+className+".prototype;\
proto.dtype='"+dtype+"';\
proto.index=function(){return this.offset};\
proto.dimension=0;\
proto.size=1;\
proto.shape=\
proto.stride=\
proto.order=[];\
proto.lo=\
proto.hi=\
proto.transpose=\
proto.step=function "+className+"_copy() {\
return new "+className+"(this.data,this.offset)\
};\
proto.pick=function "+className+"_pick(){\
return TrivialArray(this.data);\
};\
proto.valueOf=proto.get=function "+className+"_get(){\
return "+(useGetters ? "this.data.get(this.offset)" : "this.data[this.offset]")+
"};\
proto.set=function "+className+"_set(v){\
return "+(useGetters ? "this.data.set(this.offset,v)" : "this.data[this.offset]=v")+"\
};\
return function construct_"+className+"(a,b,c,d){return new "+className+"(a,d)}"
var procedure = new Function("TrivialArray", code)
return procedure(CACHED_CONSTRUCTORS[dtype][0])
}
var code = ["'use strict'"]
//Create constructor for view
var indices = iota(dimension)
var args = indices.map(function(i) { return "i"+i })
var index_str = "this.offset+" + indices.map(function(i) {
return "this.stride[" + i + "]*i" + i
}).join("+")
var shapeArg = indices.map(function(i) {
return "b"+i
}).join(",")
var strideArg = indices.map(function(i) {
return "c"+i
}).join(",")
code.push(
"function "+className+"(a," + shapeArg + "," + strideArg + ",d){this.data=a",
"this.shape=[" + shapeArg + "]",
"this.stride=[" + strideArg + "]",
"this.offset=d|0}",
"var proto="+className+".prototype",
"proto.dtype='"+dtype+"'",
"proto.dimension="+dimension)
//view.size:
code.push("Object.defineProperty(proto,'size',{get:function "+className+"_size(){\
return "+indices.map(function(i) { return "this.shape["+i+"]" }).join("*"),
"}})")
//view.order:
if(dimension === 1) {
code.push("proto.order=[0]")
} else {
code.push("Object.defineProperty(proto,'order',{get:")
if(dimension < 4) {
code.push("function "+className+"_order(){")
if(dimension === 2) {
code.push("return (Math.abs(this.stride[0])>Math.abs(this.stride[1]))?[1,0]:[0,1]}})")
} else if(dimension === 3) {
code.push(
"var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\
if(s0>s1){\
if(s1>s2){\
return [2,1,0];\
}else if(s0>s2){\
return [1,2,0];\
}else{\
return [1,0,2];\
}\
}else if(s0>s2){\
return [2,0,1];\
}else if(s2>s1){\
return [0,1,2];\
}else{\
return [0,2,1];\
}}})")
}
} else {
code.push("ORDER})")
}
}
//view.set(i0, ..., v):
code.push(
"proto.set=function "+className+"_set("+args.join(",")+",v){")
if(useGetters) {
code.push("return this.data.set("+index_str+",v)}")
} else {
code.push("return this.data["+index_str+"]=v}")
}
//view.get(i0, ...):
code.push("proto.get=function "+className+"_get("+args.join(",")+"){")
if(useGetters) {
code.push("return this.data.get("+index_str+")}")
} else {
code.push("return this.data["+index_str+"]}")
}
//view.index:
code.push(
"proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}")
//view.hi():
code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+
indices.map(function(i) {
return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("")
}).join(",")+","+
indices.map(function(i) {
return "this.stride["+i + "]"
}).join(",")+",this.offset)}")
//view.lo():
var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" })
var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" })
code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(","))
for(var i=0; i<dimension; ++i) {
code.push(
"if(typeof i"+i+"==='number'&&i"+i+">=0){\
d=i"+i+"|0;\
b+=c"+i+"*d;\
a"+i+"-=d}")
}
code.push("return new "+className+"(this.data,"+
indices.map(function(i) {
return "a"+i
}).join(",")+","+
indices.map(function(i) {
return "c"+i
}).join(",")+",b)}")
//view.step():
code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+
indices.map(function(i) {
return "a"+i+"=this.shape["+i+"]"
}).join(",")+","+
indices.map(function(i) {
return "b"+i+"=this.stride["+i+"]"
}).join(",")+",c=this.offset,d=0,ceil=Math.ceil")
for(var i=0; i<dimension; ++i) {
code.push(
"if(typeof i"+i+"==='number'){\
d=i"+i+"|0;\
if(d<0){\
c+=b"+i+"*(a"+i+"-1);\
a"+i+"=ceil(-a"+i+"/d)\
}else{\
a"+i+"=ceil(a"+i+"/d)\
}\
b"+i+"*=d\
}")
}
code.push("return new "+className+"(this.data,"+
indices.map(function(i) {
return "a" + i
}).join(",")+","+
indices.map(function(i) {
return "b" + i
}).join(",")+",c)}")
//view.transpose():
var tShape = new Array(dimension)
var tStride = new Array(dimension)
for(var i=0; i<dimension; ++i) {
tShape[i] = "a[i"+i+"]"
tStride[i] = "b[i"+i+"]"
}
code.push("proto.transpose=function "+className+"_transpose("+args+"){"+
args.map(function(n,idx) { return n + "=(" + n + "===undefined?" + idx + ":" + n + "|0)"}).join(";"),
"var a=this.shape,b=this.stride;return new "+className+"(this.data,"+tShape.join(",")+","+tStride.join(",")+",this.offset)}")
//view.pick():
code.push("proto.pick=function "+className+"_pick("+args+"){var a=[],b=[],c=this.offset")
for(var i=0; i<dimension; ++i) {
code.push("if(typeof i"+i+"==='number'&&i"+i+">=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}")
}
code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}")
//Add return statement
code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+
indices.map(function(i) {
return "shape["+i+"]"
}).join(",")+","+
indices.map(function(i) {
return "stride["+i+"]"
}).join(",")+",offset)}")
//Compile procedure
var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n"))
return procedure(CACHED_CONSTRUCTORS[dtype], order)
}
function arrayDType(data) {
if(isBuffer(data)) {
return "buffer"
}
if(hasTypedArrays) {
switch(Object.prototype.toString.call(data)) {
case "[object Float64Array]":
return "float64"
case "[object Float32Array]":
return "float32"
case "[object Int8Array]":
return "int8"
case "[object Int16Array]":
return "int16"
case "[object Int32Array]":
return "int32"
case "[object Uint8Array]":
return "uint8"
case "[object Uint16Array]":
return "uint16"
case "[object Uint32Array]":
return "uint32"
case "[object Uint8ClampedArray]":
return "uint8_clamped"
}
}
if(Array.isArray(data)) {
return "array"
}
return "generic"
}
var CACHED_CONSTRUCTORS = {
"float32":[],
"float64":[],
"int8":[],
"int16":[],
"int32":[],
"uint8":[],
"uint16":[],
"uint32":[],
"array":[],
"uint8_clamped":[],
"buffer":[],
"generic":[]
}
;(function() {
for(var id in CACHED_CONSTRUCTORS) {
CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1))
}
});
function wrappedNDArrayCtor(data, shape, stride, offset) {
if(data === undefined) {
var ctor = CACHED_CONSTRUCTORS.array[0]
return ctor([])
} else if(typeof data === "number") {
data = [data]
}
if(shape === undefined) {
shape = [ data.length ]
}
var d = shape.length
if(stride === undefined) {
stride = new Array(d)
for(var i=d-1, sz=1; i>=0; --i) {
stride[i] = sz
sz *= shape[i]
}
}
if(offset === undefined) {
offset = 0
for(var i=0; i<d; ++i) {
if(stride[i] < 0) {
offset -= (shape[i]-1)*stride[i]
}
}
}
var dtype = arrayDType(data)
var ctor_list = CACHED_CONSTRUCTORS[dtype]
while(ctor_list.length <= d+1) {
ctor_list.push(compileConstructor(dtype, ctor_list.length-1))
}
var ctor = ctor_list[d+1]
return ctor(data, shape, stride, offset)
}
module.exports = wrappedNDArrayCtor
},{"iota-array":11,"is-buffer":12}],19:[function(require,module,exports){
(function (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.
// 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 (typeof path !== 'string') {
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(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 = substr(path, -1) === '/';
// Normalize the path
path = normalizeArray(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(filter(paths, function(p, index) {
if (typeof p !== 'string') {
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];
};
function filter (xs, f) {
if (xs.filter) return xs.filter(f);
var res = [];
for (var i = 0; i < xs.length; i++) {
if (f(xs[i], i, xs)) res.push(xs[i]);
}
return res;
}
// String.prototype.substr - negative index don't work in IE8
var substr = 'ab'.substr(-1) === 'b'
? function (str, start, len) { return str.substr(start, len) }
: function (str, start, len) {
if (start < 0) start = str.length + start;
return str.substr(start, len);
}
;
}).call(this,require('_process'))
},{"_process":20}],20:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
},{}],21:[function(require,module,exports){
(function (global,Buffer){
'use strict'
var bits = require('bit-twiddle')
var dup = require('dup')
//Legacy pool support
if(!global.__TYPEDARRAY_POOL) {
global.__TYPEDARRAY_POOL = {
UINT8 : dup([32, 0])
, UINT16 : dup([32, 0])
, UINT32 : dup([32, 0])
, INT8 : dup([32, 0])
, INT16 : dup([32, 0])
, INT32 : dup([32, 0])
, FLOAT : dup([32, 0])
, DOUBLE : dup([32, 0])
, DATA : dup([32, 0])
, UINT8C : dup([32, 0])
, BUFFER : dup([32, 0])
}
}
var hasUint8C = (typeof Uint8ClampedArray) !== 'undefined'
var POOL = global.__TYPEDARRAY_POOL
//Upgrade pool
if(!POOL.UINT8C) {
POOL.UINT8C = dup([32, 0])
}
if(!POOL.BUFFER) {
POOL.BUFFER = dup([32, 0])
}
//New technique: Only allocate from ArrayBufferView and Buffer
var DATA = POOL.DATA
, BUFFER = POOL.BUFFER
exports.free = function free(array) {
if(Buffer.isBuffer(array)) {
BUFFER[bits.log2(array.length)].push(array)
} else {
if(Object.prototype.toString.call(array) !== '[object ArrayBuffer]') {
array = array.buffer
}
if(!array) {
return
}
var n = array.length || array.byteLength
var log_n = bits.log2(n)|0
DATA[log_n].push(array)
}
}
function freeArrayBuffer(buffer) {
if(!buffer) {
return
}
var n = buffer.length || buffer.byteLength
var log_n = bits.log2(n)
DATA[log_n].push(buffer)
}
function freeTypedArray(array) {
freeArrayBuffer(array.buffer)
}
exports.freeUint8 =
exports.freeUint16 =
exports.freeUint32 =
exports.freeInt8 =
exports.freeInt16 =
exports.freeInt32 =
exports.freeFloat32 =
exports.freeFloat =
exports.freeFloat64 =
exports.freeDouble =
exports.freeUint8Clamped =
exports.freeDataView = freeTypedArray
exports.freeArrayBuffer = freeArrayBuffer
exports.freeBuffer = function freeBuffer(array) {
BUFFER[bits.log2(array.length)].push(array)
}
exports.malloc = function malloc(n, dtype) {
if(dtype === undefined || dtype === 'arraybuffer') {
return mallocArrayBuffer(n)
} else {
switch(dtype) {
case 'uint8':
return mallocUint8(n)
case 'uint16':
return mallocUint16(n)
case 'uint32':
return mallocUint32(n)
case 'int8':
return mallocInt8(n)
case 'int16':
return mallocInt16(n)
case 'int32':
return mallocInt32(n)
case 'float':
case 'float32':
return mallocFloat(n)
case 'double':
case 'float64':
return mallocDouble(n)
case 'uint8_clamped':
return mallocUint8Clamped(n)
case 'buffer':
return mallocBuffer(n)
case 'data':
case 'dataview':
return mallocDataView(n)
default:
return null
}
}
return null
}
function mallocArrayBuffer(n) {
var n = bits.nextPow2(n)
var log_n = bits.log2(n)
var d = DATA[log_n]
if(d.length > 0) {
return d.pop()
}
return new ArrayBuffer(n)
}
exports.mallocArrayBuffer = mallocArrayBuffer
function mallocUint8(n) {
return new Uint8Array(mallocArrayBuffer(n), 0, n)
}
exports.mallocUint8 = mallocUint8
function mallocUint16(n) {
return new Uint16Array(mallocArrayBuffer(2*n), 0, n)
}
exports.mallocUint16 = mallocUint16
function mallocUint32(n) {
return new Uint32Array(mallocArrayBuffer(4*n), 0, n)
}
exports.mallocUint32 = mallocUint32
function mallocInt8(n) {
return new Int8Array(mallocArrayBuffer(n), 0, n)
}
exports.mallocInt8 = mallocInt8
function mallocInt16(n) {
return new Int16Array(mallocArrayBuffer(2*n), 0, n)
}
exports.mallocInt16 = mallocInt16
function mallocInt32(n) {
return new Int32Array(mallocArrayBuffer(4*n), 0, n)
}
exports.mallocInt32 = mallocInt32
function mallocFloat(n) {
return new Float32Array(mallocArrayBuffer(4*n), 0, n)
}
exports.mallocFloat32 = exports.mallocFloat = mallocFloat
function mallocDouble(n) {
return new Float64Array(mallocArrayBuffer(8*n), 0, n)
}
exports.mallocFloat64 = exports.mallocDouble = mallocDouble
function mallocUint8Clamped(n) {
if(hasUint8C) {
return new Uint8ClampedArray(mallocArrayBuffer(n), 0, n)
} else {
return mallocUint8(n)
}
}
exports.mallocUint8Clamped = mallocUint8Clamped
function mallocDataView(n) {
return new DataView(mallocArrayBuffer(n), 0, n)
}
exports.mallocDataView = mallocDataView
function mallocBuffer(n) {
n = bits.nextPow2(n)
var log_n = bits.log2(n)
var cache = BUFFER[log_n]
if(cache.length > 0) {
return cache.pop()
}
return new Buffer(n)
}
exports.mallocBuffer = mallocBuffer
exports.clearCache = function clearCache() {
for(var i=0; i<32; ++i) {
POOL.UINT8[i].length = 0
POOL.UINT16[i].length = 0
POOL.UINT32[i].length = 0
POOL.INT8[i].length = 0
POOL.INT16[i].length = 0
POOL.INT32[i].length = 0
POOL.FLOAT[i].length = 0
POOL.DOUBLE[i].length = 0
POOL.UINT8C[i].length = 0
DATA[i].length = 0
BUFFER[i].length = 0
}
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
},{"bit-twiddle":2,"buffer":3,"dup":9}],22:[function(require,module,exports){
"use strict"
function unique_pred(list, compare) {
var ptr = 1
, len = list.length
, a=list[0], b=list[0]
for(var i=1; i<len; ++i) {
b = a
a = list[i]
if(compare(a, b)) {
if(i === ptr) {
ptr++
continue
}
list[ptr++] = a
}
}
list.length = ptr
return list
}
function unique_eq(list) {
var ptr = 1
, len = list.length
, a=list[0], b = list[0]
for(var i=1; i<len; ++i, b=a) {
b = a
a = list[i]
if(a !== b) {
if(i === ptr) {
ptr++
continue
}
list[ptr++] = a
}
}
list.length = ptr
return list
}
function unique(list, compare, sorted) {
if(list.length === 0) {
return list
}
if(compare) {
if(!sorted) {
list.sort(compare)
}
return unique_pred(list, compare)
}
if(!sorted) {
list.sort()
}
return unique_eq(list)
}
module.exports = unique
},{}],23:[function(require,module,exports){
'use strict';
module.exports = {
printThreshold: 7,
nFloatingValues: 5
};
},{}],24:[function(require,module,exports){
'use strict';
module.exports = {
int8: Int8Array,
int16: Int16Array,
int32: Int32Array,
uint8: Uint8Array,
uint16: Uint16Array,
uint32: Uint32Array,
float32: Float32Array,
float64: Float64Array,
array: Array
};
},{}],25:[function(require,module,exports){
'use strict';
module.exports = {
ValueError: function ValueError () {
var err = Error.apply(this, arguments);
err.name = this.constructor.name;
return err;
},
ConfigError: function ConfigError () {
var err = Error.apply(this, arguments);
err.name = this.constructor.name;
return err;
},
NotImplementedError: function NotImplementedError () {
var err = Error.apply(this, arguments);
err.name = this.constructor.name;
return err;
}
};
},{}],26:[function(require,module,exports){
'use strict';
module.exports = function areaSum (h0, w0, H, W, SAT) {
var x0 = w0 - 1;
var x1 = w0 + W - 1;
var y0 = h0 - 1;
var y1 = h0 + H - 1;
return (w0 !== 0 && h0 !== 0) ? SAT.selection.get(y0, x0) - SAT.selection.get(y1, x0) - SAT.selection.get(y0, x1) + SAT.selection.get(y1, x1)
: (w0 === 0 && h0 === 0) ? SAT.selection.get(h0 + H - 1, w0 + W - 1)
: (w0 === 0) ? -SAT.selection.get(y0, w0 + W - 1) + SAT.selection.get(h0 + H - 1, w0 + W - 1)
: -SAT.selection.get(y1, x0) + SAT.selection.get(y1, x1);
};
},{}],27:[function(require,module,exports){
'use strict';
var areaSum = require('./area-sum');
module.exports = function areaValue (h0, w0, H, W, SAT) {
return areaSum(h0, w0, H, W, SAT) / (H * W);
};
},{"./area-sum":26}],28:[function(require,module,exports){
(function (__dirname){
'use strict';
var path = require('path');
var read = require('./read');
var DATA_DIR = path.join(path.resolve(__dirname), '../../data');
function getArray (fileName) {
return read(path.join(DATA_DIR, fileName));
}
var exports = {};
/**
* @property {NdArray} digit - 28x28 grayscale image with an handwritten digit extracted from MNIST database
*/
Object.defineProperty(exports, 'digit', {
get: function () {
return getArray('five.png');
}
});
/**
* @property {NdArray} five - 28x28 grayscale image with an handwritten digit extracted from MNIST database
*/
Object.defineProperty(exports, 'five', {
get: function () {
return getArray('five.png');
}
});
/**
* @property {NdArray} node - 300x600 COLOR image representing Node.js's logo
*/
Object.defineProperty(exports, 'node', {
get: function () {
return getArray('nodejs.png');
}
});
/**
* @property {NdArray} lena - The standard, yet sometimes controversial Lena test image was scanned from the November 1972 edition of Playboy magazine. From an image processing perspective, this image is useful because it contains smooth, textured, shaded as well as detail areas.
*/
Object.defineProperty(exports, 'lena', {
get: function () {
return getArray('lenna.png');
}
});
/**
* @property {NdArray} lenna - The standard, yet sometimes controversial Lena test image was scanned from the November 1972 edition of Playboy magazine. From an image processing perspective, this image is useful because it contains smooth, textured, shaded as well as detail areas.
*/
Object.defineProperty(exports, 'lenna', {
get: function () {
return getArray('lenna.png');
}
});
/**
* @property {NdArray} moon - This low-contrast image of the surface of the moon is useful for illustrating histogram equalization and contrast stretching.
*/
Object.defineProperty(exports, 'moon', {
get: function () {
return getArray('moon.jpg');
}
});
module.exports = exports;
}).call(this,"/src/images")
},{"./read":32,"path":19}],29:[function(require,module,exports){
'use strict';
var NdArray = require('../ndarray');
module.exports = function flipImage (img) {
return new NdArray(img.selection.step(null, -1));
};
},{"../ndarray":42}],30:[function(require,module,exports){
'use strict';
/**
* This callback type is called `imgCallback` and is displayed as a global symbol.
*
* @callback imgCallback
* @param {err} error - if any, null otherwise
* @param {NdArray} - image represented as a (H, W, [K,]) array, with K the number of color channels. if image is grayscale (or B&W) then image only have two dimensions H and W
*/
module.exports = {
data: require('./data'),
read: require('./read'),
save: require('./save'),
resize: require('./resize'),
sat: require('./sat'),
ssat: require('./ssat'),
sobel: require('./sobel'),
scharr: require('./scharr'),
areaSum: require('./area-sum'),
areaValue: require('./area-value'),
rgb2gray: require('./rgb2gray'),
flip: require('./flip')
};
},{"./area-sum":26,"./area-value":27,"./data":28,"./flip":29,"./read":32,"./resize":33,"./rgb2gray":34,"./sat":35,"./save":36,"./scharr":37,"./sobel":38,"./ssat":39}],31:[function(require,module,exports){
'use strict';
var NdArray = require('../ndarray');
var doCheckIsGrayscale = require('cwise/lib/wrapper')({"args":["array","array","array"],"pre":{"body":"{this_isgray=!0}","args":[],"thisVars":["this_isgray"],"localVars":[]},"body":{"body":"{_inline_82_arg0_===_inline_82_arg1_&&_inline_82_arg1_===_inline_82_arg2_||(this_isgray=!1)}","args":[{"name":"_inline_82_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_82_arg1_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_82_arg2_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_isgray"],"localVars":[]},"post":{"body":"{return this_isgray}","args":[],"thisVars":["this_isgray"],"localVars":[]},"debug":false,"funcName":"doCheckIsGrayscaleCwise","blockSize":64});
module.exports = function isGrayscaleImage (arr) {
if (arr instanceof NdArray) {
arr = arr.selection;
}
var aShape = arr.shape;
if (aShape.length === 1) {
return false;
}
if (aShape.length === 2 || aShape.length === 3 && aShape[2] === 1) {
return true;
} else if (aShape.length === 3 && (aShape[2] === 3 || aShape[2] === 4)) {
return doCheckIsGrayscale(arr.pick(null, null, 0), arr.pick(null, null, 1), arr.pick(null, null, 2));
}
return false;
};
},{"../ndarray":42,"cwise/lib/wrapper":8}],32:[function(require,module,exports){
'use strict';
/* global HTMLCanvasElement */
var ndarray = require('ndarray');
var NdArray = require('../ndarray');
var errors = require('../errors');
var isGrayscale = require('./is-grayscale');
module.exports = function readImageDom (input) {
if (input instanceof HTMLCanvasElement) {
return processCanvas(input);
} else if (input instanceof HTMLImageElement) {
return processImg(input);
} else {
throw new errors.ValueError('expect input to be either an HTML Canvas or a (loaded) Image');
}
};
function processCanvas (canvas) {
var context = canvas.getContext('2d');
var pixels = context.getImageData(0, 0, canvas.width, canvas.height);
var shape = [canvas.width, canvas.height, 4];
var stride = [4, 4 * canvas.width, 1];
var wxh = ndarray(new Uint8Array(pixels.data), shape, stride, 0);
var hxw = wxh.transpose(1, 0);
if (isGrayscale(hxw)) {
hxw = hxw.pick(null, null, 0);
}
return new NdArray(hxw);
}
function processImg (img) {
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
var pixels = context.getImageData(0, 0, img.width, img.height);
var shape = [img.width, img.height, 4];
var stride = [4, 4 * img.width, 1];
var wxh = ndarray(new Uint8Array(pixels.data), shape, stride, 0);
var hxw = wxh.transpose(1, 0);
if (isGrayscale(hxw)) {
hxw = hxw.pick(null, null, 0);
}
return new NdArray(hxw);
}
},{"../errors":25,"../ndarray":42,"./is-grayscale":31,"ndarray":18}],33:[function(require,module,exports){
'use strict';
var _ = require('./utils');
var ndarray = require('ndarray');
var NdArray = require('../ndarray');
module.exports = function resizeImageDom (img, height, width) {
var iShape = img.shape;
var H = iShape[0];
var W = iShape[1];
var K = iShape[2] || 1;
var originalCanvas = document.createElement('canvas');
originalCanvas.height = H; originalCanvas.width = W;
var originalCtx = originalCanvas.getContext('2d');
var originalImg = originalCtx.createImageData(W, H);
var err = _.setRawData(img.selection, originalImg.data);
if (err) { throw err; }
// compute cropping
var cfH = H / height;
var cfW = W / width;
var cf = Math.min(cfH, cfW);
var cH = height * cf;
var cW = width * cf;
var cdH = (H - cf * height) / 2;
var cdW = (W - cf * width) / 2;
originalCtx.putImageData(originalImg, 0, 0);
originalCtx.drawImage(originalCanvas, cdW, cdH, cW, cH, 0, 0, width, height);
var resizedImg = originalCtx.getImageData(0, 0, width, height);
var shape = [width | 0, height | 0, 4];
var stride = [4, 4 * width | 0, 1];
var wxh = ndarray(new Uint8Array(resizedImg.data), shape, stride, 0);
var hxw = wxh.transpose(1, 0);
if (iShape.length === 2) {
hxw = hxw.pick(null, null, 0);
} else if (iShape.length === 3 && K === 1) {
hxw = hxw.pick(null, null, 0);
}
return new NdArray(hxw);
};
},{"../ndarray":42,"./utils":40,"ndarray":18}],34:[function(require,module,exports){
'use strict';
var NdArray = require('../ndarray');
var __ = require('../utils');
// takes ~157ms on a 5000x5000 image
var doRgb2gray = require('cwise/lib/wrapper')({"args":["array","array","array","array"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_79_arg0_=4899*_inline_79_arg1_+9617*_inline_79_arg2_+1868*_inline_79_arg3_+8192>>14}","args":[{"name":"_inline_79_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_79_arg1_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_79_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_79_arg3_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"rgb2grayCwise","blockSize":64});
/**
* Compute Grayscale version of an RGB image.
* @param {NdArray} img The image in RGB format. In a 3-D array of shape (h, w, 3), or in RGBA format with shape (h, w, 4).
* @returns {NdArray} The grayscale image, a 3-D array of shape (h, w, 1).
*/
module.exports = function rgb2gray (img) {
if (!(img instanceof NdArray)) {
img = new NdArray(img); // assume it is an ndarray
}
var iShape = img.shape;
var h = iShape[0];
var w = iShape[1];
var k = (iShape[2] || 1);
if (k === 1) {
return img; // already gray
}
var oShape = [h, w];
var out = new NdArray(new Uint8Array(__.shapeSize(oShape)), oShape);
var r = img.selection.pick(null, null, 0);
var g = img.selection.pick(null, null, 1);
var b = img.selection.pick(null, null, 2);
doRgb2gray(out.selection, r, g, b);
return out;
};
},{"../ndarray":42,"../utils":43,"cwise/lib/wrapper":8}],35:[function(require,module,exports){
'use strict';
var NdArray = require('../ndarray');
var rgb2gray = require('./rgb2gray');
var doIntegrate = require('cwise/lib/wrapper')({"args":["array","array","index",{"offset":[-1,-1],"array":0},{"offset":[-1,0],"array":0},{"offset":[0,-1],"array":0}],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_67_arg0_=0!==_inline_67_arg2_[0]&&0!==_inline_67_arg2_[1]?_inline_67_arg1_+_inline_67_arg4_+_inline_67_arg5_-_inline_67_arg3_:0===_inline_67_arg2_[0]&&0===_inline_67_arg2_[1]?_inline_67_arg1_:0===_inline_67_arg2_[0]?_inline_67_arg1_+_inline_67_arg5_:_inline_67_arg1_+_inline_67_arg4_}","args":[{"name":"_inline_67_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_67_arg1_","lvalue":false,"rvalue":true,"count":4},{"name":"_inline_67_arg2_","lvalue":false,"rvalue":true,"count":5},{"name":"_inline_67_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_67_arg4_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_67_arg5_","lvalue":false,"rvalue":true,"count":2}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"doIntegrateBody","blockSize":64});
/**
* Compute Sum Area Table, also known as the integral of the image
* @param {NdArray} img
* @returns {NdArray}
*/
module.exports = function computeSumAreaTable (img) {
var gray = rgb2gray(img);
var iShape = gray.shape;
var iH = iShape[0];
var iW = iShape[1];
var out = new NdArray(new Uint32Array(iH * iW), [iH, iW]);
doIntegrate(out.selection, gray.selection);
return out;
};
},{"../ndarray":42,"./rgb2gray":34,"cwise/lib/wrapper":8}],36:[function(require,module,exports){
'use strict';
var _ = require('./utils');
var errors = require('../errors');
/**
* Save image on the given destination
*
* @param {NdArray} img
* @param {HTMLCanvasElement} dest
*/
module.exports = function saveImageDom (img, dest) {
var iShape = img.shape;
var iH = iShape[0];
var iW = iShape[1];
if (dest instanceof HTMLCanvasElement) {
var $tmp = document.createElement('canvas');
$tmp.height = iH; $tmp.width = iW;
var tmpCtx = $tmp.getContext('2d');
var originalImg = tmpCtx.createImageData(iW, iH);
var err = _.setRawData(img.selection, originalImg.data);
if (err) { throw err; }
tmpCtx.putImageData(originalImg, 0, 0);
tmpCtx.drawImage($tmp, iW, iH);
dest.getContext('2d').drawImage($tmp, 0, 0, iW, iH, 0, 0, dest.width, dest.height);
} else {
throw new errors.ValueError('expect input to be either an HTML Canvas or a (loaded) Image');
}
};
},{"../errors":25,"./utils":40}],37:[function(require,module,exports){
'use strict';
var ops = require('ndarray-ops');
var NdArray = require('../ndarray');
var __ = require('../utils');
var rgb2gray = require('./rgb2gray');
var doScharr = require('cwise/lib/wrapper')({"args":["array","array",{"offset":[-1,-1],"array":1},{"offset":[-1,0],"array":1},{"offset":[-1,1],"array":1},{"offset":[0,-1],"array":1},{"offset":[0,1],"array":1},{"offset":[1,-1],"array":1},{"offset":[1,0],"array":1},{"offset":[1,1],"array":1}],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{var _inline_76_q=3*_inline_76_arg2_+10*_inline_76_arg3_+3*_inline_76_arg4_-3*_inline_76_arg7_-10*_inline_76_arg8_-3*_inline_76_arg9_,_inline_76_s=3*_inline_76_arg2_-3*_inline_76_arg4_+10*_inline_76_arg5_-10*_inline_76_arg6_+3*_inline_76_arg7_-3*_inline_76_arg9_;_inline_76_arg0_=Math.sqrt(_inline_76_s*_inline_76_s+_inline_76_q*_inline_76_q)}","args":[{"name":"_inline_76_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_76_arg1_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_76_arg2_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_76_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_76_arg4_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_76_arg5_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_76_arg6_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_76_arg7_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_76_arg8_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_76_arg9_","lvalue":false,"rvalue":true,"count":2}],"thisVars":[],"localVars":["_inline_76_q","_inline_76_s"]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"doSobelBody","blockSize":64});
/**
* Find the edge magnitude using the Scharr transform.
*
* @note
* Take the square root of the sum of the squares of the horizontal and vertical Scharrs to get a magnitude
* that is somewhat insensitive to direction. The Scharr operator has a better rotation invariance than other
* edge filters, such as the Sobel operators.
*
* @param {NdArray} img
*/
module.exports = function computeScharr (img) {
var gray = rgb2gray(img);
var iShape = gray.shape;
var iH = iShape[0];
var iW = iShape[1];
var out = new NdArray(new Float32Array(__.shapeSize(iShape)), iShape);
doScharr(out.selection, gray.selection);
// set borders to zero (invalid anyway)
ops.assigns(out.selection.pick(0, null), 0); // first line
ops.assigns(out.selection.pick(null, 0), 0); // first col
ops.assigns(out.selection.pick(iH - 1, null), 0); // last line
ops.assigns(out.selection.pick(null, iW - 1), 0); // last col
return out.divide(16 * Math.sqrt(2), false);
};
},{"../ndarray":42,"../utils":43,"./rgb2gray":34,"cwise/lib/wrapper":8,"ndarray-ops":17}],38:[function(require,module,exports){
'use strict';
var ops = require('ndarray-ops');
var NdArray = require('../ndarray');
var __ = require('../utils');
var rgb2gray = require('./rgb2gray');
var doSobel = require('cwise/lib/wrapper')({"args":["array","array",{"offset":[-1,-1],"array":1},{"offset":[-1,0],"array":1},{"offset":[-1,1],"array":1},{"offset":[0,-1],"array":1},{"offset":[0,1],"array":1},{"offset":[1,-1],"array":1},{"offset":[1,0],"array":1},{"offset":[1,1],"array":1}],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{var _inline_73_q=_inline_73_arg2_+2*_inline_73_arg3_+_inline_73_arg4_-_inline_73_arg7_-2*_inline_73_arg8_-_inline_73_arg9_,_inline_73_s=_inline_73_arg2_-_inline_73_arg4_+2*_inline_73_arg5_-2*_inline_73_arg6_+_inline_73_arg7_-_inline_73_arg9_;_inline_73_arg0_=Math.sqrt(_inline_73_s*_inline_73_s+_inline_73_q*_inline_73_q)}","args":[{"name":"_inline_73_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_73_arg1_","lvalue":false,"rvalue":false,"count":0},{"name":"_inline_73_arg2_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_73_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_73_arg4_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_73_arg5_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_73_arg6_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_73_arg7_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_73_arg8_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_73_arg9_","lvalue":false,"rvalue":true,"count":2}],"thisVars":[],"localVars":["_inline_73_q","_inline_73_s"]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"doSobelBody","blockSize":64});
/**
* Find the edge magnitude using the Sobel transform.
*
* @note
* Take the square root of the sum of the squares of the horizontal and vertical Sobels to get a magnitude that’s somewhat insensitive to direction.
*
* The 3x3 convolution kernel used in the horizontal and vertical Sobels is an approximation of the
* gradient of the image (with some slight blurring since 9 pixels are used to compute the gradient at a given pixel).
* As an approximation of the gradient, the Sobel operator is not completely rotation-invariant. The Scharr operator should be used for a better rotation invariance.
* @param {NdArray} img
*/
module.exports = function computeSobel (img) {
var gray = rgb2gray(img);
var iShape = gray.shape;
var iH = iShape[0];
var iW = iShape[1];
var out = new NdArray(new Float32Array(__.shapeSize(iShape)), iShape);
doSobel(out.selection, gray.selection);
// set borders to zero (invalid anyway)
ops.assigns(out.selection.pick(0, null), 0); // first line
ops.assigns(out.selection.pick(null, 0), 0); // first col
ops.assigns(out.selection.pick(iH - 1, null), 0); // last line
ops.assigns(out.selection.pick(null, iW - 1), 0); // last col
return out.divide(4 * Math.sqrt(2), false);
};
},{"../ndarray":42,"../utils":43,"./rgb2gray":34,"cwise/lib/wrapper":8,"ndarray-ops":17}],39:[function(require,module,exports){
'use strict';
var NdArray = require('../ndarray');
var rgb2gray = require('./rgb2gray');
var doIntegrate = require('cwise/lib/wrapper')({"args":["array","array","index",{"offset":[-1,-1],"array":0},{"offset":[-1,0],"array":0},{"offset":[0,-1],"array":0}],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_70_arg0_=0!==_inline_70_arg2_[0]&&0!==_inline_70_arg2_[1]?_inline_70_arg1_*_inline_70_arg1_+_inline_70_arg4_+_inline_70_arg5_-_inline_70_arg3_:0===_inline_70_arg2_[0]&&0===_inline_70_arg2_[1]?_inline_70_arg1_*_inline_70_arg1_:0===_inline_70_arg2_[0]?_inline_70_arg1_*_inline_70_arg1_+_inline_70_arg5_:_inline_70_arg1_*_inline_70_arg1_+_inline_70_arg4_}","args":[{"name":"_inline_70_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_70_arg1_","lvalue":false,"rvalue":true,"count":8},{"name":"_inline_70_arg2_","lvalue":false,"rvalue":true,"count":5},{"name":"_inline_70_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_70_arg4_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_70_arg5_","lvalue":false,"rvalue":true,"count":2}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"doIntegrateBody","blockSize":64});
/**
* Compute Squared Sum Area Table, also known as the integral of the squared image
* @param {NdArray} img
* @returns {NdArray}
*/
module.exports = function computeSquaredSumAreaTable (img) {
var gray = rgb2gray(img);
var iShape = gray.shape;
var iH = iShape[0];
var iW = iShape[1];
var out = new NdArray(new Uint32Array(iH * iW), [iH, iW]);
doIntegrate(out.selection, gray.selection);
return out;
};
},{"../ndarray":42,"./rgb2gray":34,"cwise/lib/wrapper":8}],40:[function(require,module,exports){
'use strict';
var NdArray = require('../ndarray');
/**
*
* @param {NdArray} array
* @returns {*}
*/
module.exports.getRawData = function getRawData (array) {
if (array instanceof NdArray) {
array = array.selection; // faster
}
var h;
var w;
var ptr = 0;
var aShape = array.shape;
var H = aShape[0];
var W = aShape[1];
var K = (aShape[2] || 1);
var data = new Uint8Array(H * W * K);
if (array.shape.length === 3) {
if (K === 3) {
for (h = 0; h < H; ++h) {
for (w = 0; w < W; ++w) {
data[ptr++] = array.get(h, w, 0);
data[ptr++] = array.get(h, w, 1);
data[ptr++] = array.get(h, w, 2);
}
}
} else if (K === 4) {
for (h = 0; h < H; ++h) {
for (w = 0; w < W; ++w) {
data[ptr++] = array.get(h, w, 0);
data[ptr++] = array.get(h, w, 1);
data[ptr++] = array.get(h, w, 2);
data[ptr++] = array.get(h, w, 3);
}
}
} else if (K === 1) {
for (h = 0; h < H; ++h) {
for (w = 0; w < W; ++w) {
data[ptr++] = array.get(h, w, 0);
}
}
} else {
return new Error('Incompatible array shape');
}
} else if (array.shape.length === 2) {
for (h = 0; h < H; ++h) {
for (w = 0; w < W; ++w) {
data[ptr++] = array.get(h, w);
}
}
} else {
return new Error('Invalid image');
}
return data;
};
module.exports.setRawData = function setRawData (array, data) {
var h;
var w;
var ptr = 0;
var c;
var H = array.shape[0];
var W = array.shape[1];
var K = array.shape[2] || 1;
if (array.shape.length === 3) {
if (K === 3) {
for (h = 0; h < H; ++h) {
for (w = 0; w < W; ++w) {
data[ptr++] = array.get(h, w, 0);
data[ptr++] = array.get(h, w, 1);
data[ptr++] = array.get(h, w, 2);
data[ptr++] = 255;
}
}
} else if (K === 4) {
for (h = 0; h < H; ++h) {
for (w = 0; w < W; ++w) {
data[ptr++] = array.get(h, w, 0);
data[ptr++] = array.get(h, w, 1);
data[ptr++] = array.get(h, w, 2);
data[ptr++] = array.get(h, w, 3);
}
}
} else if (K === 1) {
for (h = 0; h < H; ++h) {
for (w = 0; w < W; ++w) {
c = array.get(h, w, 0);
data[ptr++] = c;
data[ptr++] = c;
data[ptr++] = c;
data[ptr++] = 255;
}
}
} else {
return new Error('Incompatible array shape');
}
} else if (array.shape.length === 2) {
for (h = 0; h < H; ++h) {
for (w = 0; w < W; ++w) {
c = array.get(h, w);
data[ptr++] = c;
data[ptr++] = c;
data[ptr++] = c;
data[ptr++] = 255;
}
}
} else {
return new Error('Invalid image');
}
};
},{"../ndarray":42}],41:[function(require,module,exports){
'use strict';
var ndarray = require('ndarray');
var ops = require('ndarray-ops');
var ndFFT = require('ndarray-fft');
var CONF = require('./config');
var DTYPES = require('./dtypes');
var NdArray = require('./ndarray');
var _ = require('./utils');
var errors = require('./errors');
function broadcast (shape1, shape2) {
if (shape1.length === 0 || shape2.length === 0) {
return;
}
var reversed1 = shape1.slice().reverse();
var reversed2 = shape2.slice().reverse();
var maxLength = Math.max(shape1.length, shape2.length);
var outShape = new Array(maxLength);
for (var i = 0; i < maxLength; i++) {
if (!reversed1[i] || reversed1[i] === 1) {
outShape[i] = reversed2[i];
} else if (!reversed2[i] || reversed2[i] === 1) {
outShape[i] = reversed1[i];
} else if (reversed1[i] === reversed2[i]) {
outShape[i] = reversed1[i];
} else {
return;
}
}
return outShape.reverse();
}
/**
* Add arguments, element-wise.
*
* @param {(NdArray|Array|number)} a
* @param {(NdArray|Array|number)} b
* @returns {NdArray}
*/
function add (a, b) {
return NdArray.new(a).add(b);
}
/**
* Multiply arguments, element-wise.
*
* @param {(Array|NdArray)} a
* @param {(Array|NdArray|number)} b
* @returns {NdArray}
*/
function multiply (a, b) {
return NdArray.new(a).multiply(b);
}
/**
* Divide `a` by `b`, element-wise.
*
* @param {(Array|NdArray)} a
* @param {(Array|NdArray|number)} b
* @returns {NdArray}
*/
function divide (a, b) {
return NdArray.new(a).divide(b);
}
/**
* Subtract second argument from the first, element-wise.
*
* @param {(NdArray|Array|number)} a
* @param {(NdArray|Array|number)} b
* @returns {NdArray}
*/
function subtract (a, b) {
return NdArray.new(a).subtract(b);
}
/**
* Return true if two arrays have the same shape and elements, false otherwise.
* @param {(Array|NdArray)} array1
* @param {(Array|NdArray)} array2
* @returns {boolean}
*/
function equal (array1, array2) {
return NdArray.new(array1).equal(array2);
}
/**
* Return a copy of the array collapsed into one dimension using row-major order (C-style)
* @param {(Array|NdArray)} array
* @returns {NdArray}
*/
function flatten (array) {
return NdArray.new(array).flatten();
}
/**
* Gives a new shape to an array without changing its data.
* @param {(Array|NdArray)} array
* @param {Array} shape - The new shape should be compatible with the original shape. If an integer, then the result will be a 1-D array of that length
* @returns {NdArray}
*/
function reshape (array, shape) {
return NdArray.new(array).reshape(shape);
}
/**
* Calculate the exponential of all elements in the input array, element-wise.
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function exp (x) {
return NdArray.new(x).exp();
}
/**
* Calculate the positive square-root of all elements in the input array, element-wise.
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function sqrt (x) {
return NdArray.new(x).sqrt();
}
/**
* Raise first array elements to powers from second array, element-wise.
*
* @param {(Array|NdArray|number)} x1
* @param {(Array|NdArray|number)} x2
* @returns {NdArray}
*/
function power (x1, x2) {
return NdArray.new(x1).pow(x2);
}
/**
* Return the sum of input array elements.
*
* @param {(Array|NdArray|number)} x
* @returns {number}
*/
function sum (x) {
return NdArray.new(x).sum();
}
/**
* Return the arithmetic mean of input array elements.
*
* @param {(Array|NdArray|number)} x
* @returns {number}
*/
function mean (x) {
return NdArray.new(x).mean();
}
/**
* Returns the standard deviation, a measure of the spread of a distribution, of the input array elements.
*
* @param {(Array|NdArray|number)} x
* @returns {number}
*/
function std (x) {
return NdArray.new(x).std();
}
/**
* Return the minimum value of the array
*
* @param {(Array|NdArray|number)} x
* @returns {Number}
*/
function min (x) {
return NdArray.new(x).min();
}
/**
* Return the maximum value of the array
*
* @param {(Array|NdArray|number)} x
* @returns {Number}
*/
function max (x) {
return NdArray.new(x).max();
}
/**
* Permute the dimensions of the input array according to the given axes.
*
* @param {(Array|NdArray|number)} x
* @param {(number|...number)} [axes]
* @returns {NdArray}
* @example
*
arr = nj.arange(6).reshape(1,2,3)
// array([[[ 0, 1, 2],
// [ 3, 4, 5]]])
arr.T
// array([[[ 0],
// [ 3]],
// [[ 1],
// [ 4]],
// [[ 2],
// [ 5]]])
arr.transpose(1,0,2)
// array([[[ 0, 1, 2]],
// [[ 3, 4, 5]]])
*/
function transpose (x, axes) {
return NdArray.new(x).transpose(axes);
}
/**
* Return the inverse of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function negative (x) {
return NdArray.new(x).negative();
}
/**
* Return evenly spaced values within a given interval.
*
* @param {int} [start=0] - Start of interval. The interval includes this value.
* @param {int} stop - End of interval. The interval does not include this value.
* @param {int} [step=1] - Spacing between values. The default step size is 1. If step is specified, start must also be given.
* @param {(String|Object)} [dtype=Array] The type of the output array.
*
* @return {NdArray} Array of evenly spaced values.
*/
function arange (start, stop, step, dtype) {
if (arguments.length === 1) {
return arange(0, start, 1, undefined);
} else if (arguments.length === 2 && _.isNumber(stop)) {
return arange(start, stop, 1, undefined);
} else if (arguments.length === 2) {
return arange(0, start, 1, stop);
} else if (arguments.length === 3 && !_.isNumber(step)) {
return arange(start, stop, 1, step);
}
var result = [];
var i = 0;
while (start < stop) {
result[i++] = start;
start += step;
}
return NdArray.new(result, dtype);
}
/**
* Return a new array of given shape and type, filled with zeros.
*
* @param {(Array|int)} shape - Shape of the new array, e.g., [2, 3] or 2.
* @param {(String|Object)} [dtype=Array] The type of the output array.
*
* @return {NdArray} Array of zeros with the given shape and dtype
*/
function zeros (shape, dtype) {
if (_.isNumber(shape) && shape >= 0) {
shape = [shape];
}
var s = _.shapeSize(shape);
var T = _.getType(dtype);
var arr = new NdArray(new T(s), shape);
if (arr.dtype === 'array') {
ops.assigns(arr.selection, 0);
}
return arr;
}
/**
* Return a new array of given shape and type, filled with ones.
*
* @param {(Array|int)} shape - Shape of the new array, e.g., [2, 3] or 2.
* @param {(String|Object)} [dtype=Array] - The type of the output array.
*
* @return {NdArray} Array of ones with the given shape and dtype
*/
function ones (shape, dtype) {
if (_.isNumber(shape) && shape >= 0) {
shape = [shape];
}
var s = _.shapeSize(shape);
var T = _.getType(dtype);
var arr = new NdArray(new T(s), shape);
ops.assigns(arr.selection, 1);
return arr;
}
/**
* Return a new array of given shape and type, filled with `undefined` values.
*
* @param {(Array|int)} shape - Shape of the new array, e.g., [2, 3] or 2.
* @param {(String|Object)} [dtype=Array] - The type of the output array.
*
* @return {NdArray} Array of `undefined` values with the given shape and dtype
*/
function empty (shape, dtype) {
if (_.isNumber(shape) && shape >= 0) {
shape = [shape];
}
var s = _.shapeSize(shape);
var T = _.getType(dtype);
return new NdArray(new T(s), shape);
}
/**
* Create an array of the given shape and propagate it with random samples from a uniform distribution over [0, 1].
* @param {number|Array|...number} shape - The dimensions of the returned array, should all be positive integers
* @returns {NdArray}
*/
function random (shape) {
if (arguments.length === 0) {
return NdArray.new(Math.random());
} else if (arguments.length === 1) {
shape = _.isNumber(shape) ? [shape | 0] : shape;
} else {
shape = [].slice.call(arguments);
}
var s = _.shapeSize(shape);
var arr = new NdArray(new Float64Array(s), shape);
ops.random(arr.selection);
return arr;
}
/**
* Return the softmax, or normalized exponential, of the input array, element-wise.
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function softmax (x) {
var e = NdArray.new(x).exp();
var se = e.sum(); // scalar
ops.divseq(e.selection, se);
return e;
}
var doSigmoid = require('cwise/lib/wrapper')({"args":["array","scalar"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_43_arg0_=_inline_43_arg0_<-30?0:_inline_43_arg0_>30?1:1/(1+Math.exp(-1*_inline_43_arg1_*_inline_43_arg0_))}","args":[{"name":"_inline_43_arg0_","lvalue":true,"rvalue":true,"count":4},{"name":"_inline_43_arg1_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"sigmoidCwise","blockSize":64});
/**
* Return the sigmoid of the input array, element-wise.
* @param {(Array|NdArray|number)} x
* @param {number} [t=1] - stifness parameter
* @returns {NdArray}
*/
function sigmoid (x, t) {
x = NdArray.new(x).clone();
t = t || 1;
doSigmoid(x.selection, t);
return x;
}
var doClip = require('cwise/lib/wrapper')({"args":["array","scalar","scalar"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_46_arg0_=Math.min(Math.max(_inline_46_arg1_,_inline_46_arg0_),_inline_46_arg2_)}","args":[{"name":"_inline_46_arg0_","lvalue":true,"rvalue":true,"count":2},{"name":"_inline_46_arg1_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_46_arg2_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"clipCwise","blockSize":64});
/**
* Clip (limit) the values in an array between min and max, element-wise.
*
* @param {(Array|NdArray|number)} x
* @param {number} [min=0]
* @param {number} [max=1]
* @returns {NdArray}
*/
function clip (x, min, max) {
if (arguments.length === 1) {
min = 0;
max = 1;
} else if (arguments.length === 2) {
max = 1;
}
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
doClip(s.selection, min, max);
return s;
}
var doLeakyRelu = require('cwise/lib/wrapper')({"args":["array","scalar"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_49_arg0_=Math.max(_inline_49_arg1_*_inline_49_arg0_,_inline_49_arg0_)}","args":[{"name":"_inline_49_arg0_","lvalue":true,"rvalue":true,"count":3},{"name":"_inline_49_arg1_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"leakyReluCwise","blockSize":64});
function leakyRelu (x, alpha) {
alpha = alpha || 1e-3;
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
doLeakyRelu(s.selection, alpha);
return s;
}
var doTanh = require('cwise/lib/wrapper')({"args":["array"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_52_arg0_=(Math.exp(2*_inline_52_arg0_)-1)/(Math.exp(2*_inline_52_arg0_)+1)}","args":[{"name":"_inline_52_arg0_","lvalue":true,"rvalue":true,"count":3}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"tanhCwise","blockSize":64});
/**
* Return hyperbolic tangent of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function tanh (x) {
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
doTanh(s.selection);
return s;
}
/**
* Return absolute value of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function abs (x) {
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
ops.abseq(s.selection);
return s;
}
/**
* Return trigonometric cosine of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function cos (x) {
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
ops.coseq(s.selection);
return s;
}
/**
* Return trigonometric inverse cosine of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function arccos (x) {
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
ops.acoseq(s.selection);
return s;
}
/**
* Return trigonometric sine of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function sin (x) {
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
ops.sineq(s.selection);
return s;
}
/**
* Return trigonometric inverse sine of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function arcsin (x) {
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
ops.asineq(s.selection);
return s;
}
/**
* Return trigonometric tangent of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function tan (x) {
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
ops.taneq(s.selection);
return s;
}
/**
* Return trigonometric inverse tangent of the input array, element-wise.
*
* @param {(Array|NdArray|number)} x
* @returns {NdArray}
*/
function arctan (x) {
var s = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
ops.ataneq(s.selection);
return s;
}
/**
* Dot product of two arrays.
*
* WARNING: supported products are:
* - matrix dot matrix
* - vector dot vector
* - matrix dot vector
* - vector dot matrix
* @param {(Array|NdArray)} a
* @param {(Array|NdArray)} b
* @returns {NdArray}
*/
function dot (a, b) {
return NdArray.new(a).dot(b);
}
/**
* Join given arrays along the last axis.
*
* @param {...(Array|NdArray)} arrays
* @returns {NdArray}
*/
function concatenate (arrays) {
if (arguments.length > 1) {
arrays = [].slice.call(arguments);
}
var i, a;
for (i = 0; i < arrays.length; i++) {
a = arrays[i];
arrays[i] = (a instanceof NdArray) ? a.tolist() : _.isNumber(a) ? [a] : a;
}
var m = arrays[0];
for (i = 1; i < arrays.length; i++) {
a = arrays[i];
var mShape = _.getShape(m);
var aShape = _.getShape(a);
if (mShape.length !== aShape.length) {
throw new errors.ValueError('all the input arrays must have same number of dimensions');
} else if (mShape.length === 1 && aShape.length === 1) {
m = m.concat(a);
} else if ((mShape.length === 2 && aShape.length === 2 && mShape[0] === aShape[0]) ||
(mShape.length === 1 && aShape.length === 2 && mShape[0] === aShape[0]) ||
(mShape.length === 2 && aShape.length === 1 && mShape[0] === aShape[0])) {
for (var row = 0; row < mShape[0]; row++) {
m[row] = m[row].concat(a[row]);
}
} else if ((mShape.length === 3 && aShape.length === 3 && mShape[0] === aShape[0] && mShape[1] === aShape[1]) ||
(mShape.length === 2 && aShape.length === 3 && mShape[0] === aShape[0] && mShape[1] === aShape[1]) ||
(mShape.length === 3 && aShape.length === 2 && mShape[0] === aShape[0] && mShape[1] === aShape[1])) {
for (var rowI = 0; rowI < mShape[0]; rowI++) {
var rowV = new Array(mShape[1]);
for (var colI = 0; colI < mShape[1]; colI++) {
rowV[colI] = m[rowI][colI].concat(a[rowI][colI]);
}
m[rowI] = rowV;
}
} else {
throw new errors.ValueError('cannot concatenate "' + mShape + '" with "' + aShape + '"');
}
}
return NdArray.new(m, arrays[0].dtype);
}
/**
* Round an array to the to the nearest integer.
*
* @param {(Array|NdArray)} x
* @returns {NdArray}
*/
function round (x) {
return NdArray.new(x).round();
}
/**
* Convolve 2 N-dimensionnal arrays
*
* @note: Arrays must have the same dimensions and a must be greater than b.
* @note: The convolution product is only given for points where the signals overlap completely. Values outside the signal boundary have no effect. This behaviour is known as the 'valid' mode.
*
* @param {Array|NdArray} a
* @param {Array|NdArray} b
*/
function convolve (a, b) {
return NdArray.new(a).convolve(b);
}
/**
* Convolve 2 N-dimensionnal arrays using Fast Fourier Transform (FFT)
*
* @note: Arrays must have the same dimensions and a must be greater than b.
* @note: The convolution product is only given for points where the signals overlap completely. Values outside the signal boundary have no effect. This behaviour is known as the 'valid' mode.
*
* @param {Array|NdArray} a
* @param {Array|NdArray} b
*/
function fftconvolve (a, b) {
return NdArray.new(a).fftconvolve(b);
}
function fft (x) {
x = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
var xShape = x.shape;
var d = xShape.length;
if (xShape[d - 1] !== 2) {
throw new errors.ValueError('expect last dimension of the array to have 2 values (for both real and imaginary part)');
}
var rPicker = new Array(d);
var iPicker = new Array(d);
rPicker[d - 1] = 0;
iPicker[d - 1] = 1;
ndFFT(1, x.selection.pick.apply(x.selection, rPicker), x.selection.pick.apply(x.selection, iPicker));
return x;
}
function ifft (x) {
x = (x instanceof NdArray) ? x.clone() : NdArray.new(x);
var xShape = x.shape;
var d = xShape.length;
if (xShape[d - 1] !== 2) {
throw new errors.ValueError('expect last dimension of the array to have 2 values (for both real and imaginary part)');
}
var rPicker = new Array(d);
var iPicker = new Array(d);
rPicker[d - 1] = 0;
iPicker[d - 1] = 1;
ndFFT(-1, x.selection.pick.apply(x.selection, rPicker), x.selection.pick.apply(x.selection, iPicker));
return x;
}
module.exports = {
config: CONF,
dtypes: DTYPES,
NdArray: NdArray,
ndarray: ndarray,
array: NdArray.new,
arange: arange,
reshape: reshape,
zeros: zeros,
ones: ones,
empty: empty,
flatten: flatten,
random: random,
softmax: softmax,
sigmoid: sigmoid,
leakyRelu: leakyRelu,
abs: abs,
arccos: arccos,
arcsin: arcsin,
arctan: arctan,
cos: cos,
sin: sin,
tan: tan,
tanh: tanh,
clip: clip,
exp: exp,
sqrt: sqrt,
power: power,
sum: sum,
mean: mean,
std: std,
dot: dot,
add: add,
subtract: subtract,
multiply: multiply,
divide: divide,
negative: negative,
equal: equal,
max: max,
min: min,
concatenate: concatenate,
transpose: transpose,
errors: errors,
broadcast: broadcast,
round: round,
convolve: convolve,
fftconvolve: fftconvolve,
fft: fft,
ifft: ifft,
int8: function (array) { return NdArray.new(array, 'int8'); },
uint8: function (array) { return NdArray.new(array, 'uint8'); },
int16: function (array) { return NdArray.new(array, 'int16'); },
uint16: function (array) { return NdArray.new(array, 'uint16'); },
int32: function (array) { return NdArray.new(array, 'int32'); },
uint32: function (array) { return NdArray.new(array, 'uint32'); },
float32: function (array) { return NdArray.new(array, 'float32'); },
float64: function (array) { return NdArray.new(array, 'float64'); },
images: require('./images')
};
},{"./config":23,"./dtypes":24,"./errors":25,"./images":30,"./ndarray":42,"./utils":43,"cwise/lib/wrapper":8,"ndarray":18,"ndarray-fft":13,"ndarray-ops":17}],42:[function(require,module,exports){
'use strict';
var ndarray = require('ndarray');
var ops = require('ndarray-ops');
var gemm = require('ndarray-gemm');
var ndFFT = require('ndarray-fft');
var ndPool = require('typedarray-pool');
var CONF = require('./config');
var errors = require('./errors');
var _ = require('./utils');
/**
* Multidimensional, homogeneous array of fixed-size items
*
* The number of dimensions and items in an array is defined by its shape, which is a tuple of N positive
* integers that specify the sizes of each dimension. The type of items in the array is specified by a separate
* data-type object (dtype), one of which is associated with each NdArray.
* @constructor
*/
var NdArray = function NdArray () {
if (arguments.length === 1) {
this.selection = arguments[0];
} else if (arguments.length === 0) {
throw new errors.ValueError("Required argument 'data' not found");
} else {
this.selection = ndarray.apply(null, arguments);
}
/**
* @property {Number} NdArray#size - Number of elements in the array.
*/
Object.defineProperty(this, 'size', {
get: function () {
return this.selection.size;
}.bind(this)
});
/**
* The shape of the array
*
* @property {Array}
* @name NdArray#shape
* @readonly
*/
Object.defineProperty(this, 'shape', {
get: function () {
return this.selection.shape;
}.bind(this)
});
/**
* Number of array dimensions.
*
* @property {Number}
* @name NdArray#ndim
* @readonly
*/
Object.defineProperty(this, 'ndim', {
get: function () {
return this.selection.shape.length;
}.bind(this)
});
/**
* Data-type of the array’s elements.
*
* @property {String}
* @name NdArray#dtype
* @see {dtypes} for more information
*/
Object.defineProperty(this, 'dtype', {
get: function () {
return this.selection.dtype;
}.bind(this),
set: function (dtype) {
var T = _.getType(dtype);
if (T !== _.getType(this.dtype)) {
this.selection = ndarray(new T(this.selection.data), this.selection.shape, this.selection.stride, this.selection.offset);
}
}.bind(this)
});
/**
* Permute the dimensions of the array.
*
* @property {String}
* @name NdArray#T
* @readonly
*/
Object.defineProperty(this, 'T', {
get: function () {
return this.transpose();
}.bind(this)
});
};
NdArray.prototype.get = function () {
var n = arguments.length;
for (var i = 0; i < n; i++) {
if (arguments[i] < 0) {
arguments[i] += this.shape[i];
}
}
return this.selection.get.apply(this.selection, arguments);
};
NdArray.prototype.set = function () {
return this.selection.set.apply(this.selection, arguments);
};
NdArray.prototype.slice = function () {
var d = this.ndim;
var hi = new Array(d);
var lo = new Array(d);
var step = new Array(d);
var tShape = this.shape;
for (var i = 0; i < d; i++) {
var arg = arguments[i];
if (typeof arg === 'undefined') { break; }
if (arg === null) { continue; }
if (_.isNumber(arg)) {
lo[i] = (arg < 0) ? arg + tShape[i] : arg;
hi[i] = null;
step[i] = 1;
} else {
// assume it is an array
var start = (arg[0] < 0) ? arg[0] + tShape[i] : arg[0];
var end = (arg[1] < 0) ? arg[1] + tShape[i] : arg[1];
lo[i] = end ? start : 0;
hi[i] = end ? end - start : start;
step[i] = arg[2] || 1;
}
}
var slo = this.selection.lo.apply(this.selection, lo);
var shi = slo.hi.apply(slo, hi);
var sstep = shi.step.apply(shi, step);
return new NdArray(sstep);
};
/**
* Return a subarray by fixing a particular axis
*
* @param {...(number|null)} axis
* @returns {NdArray}
*
* @example
arr = nj.arange(4*4).reshape(4,4)
// array([[ 0, 1, 2, 3],
// [ 4, 5, 6, 7],
// [ 8, 9, 10, 11],
// [ 12, 13, 14, 15]])
arr.pick(1)
// array([ 4, 5, 6, 7])
arr.pick(null, 1)
// array([ 1, 5, 9, 13])
*/
NdArray.prototype.pick = function (axis) {
return new NdArray(this.selection.pick.apply(this.selection, arguments));
};
/**
* Return a shifted view of the array. Think of it as taking the upper left corner of the image and dragging it inward
*
* @returns {NdArray}
*
* @example
arr = nj.arange(4*4).reshape(4,4)
// array([[ 0, 1, 2, 3],
// [ 4, 5, 6, 7],
// [ 8, 9, 10, 11],
// [ 12, 13, 14, 15]])
arr.lo(1,1)
// array([[ 5, 6, 7],
// [ 9, 10, 11],
// [ 13, 14, 15]])
*/
NdArray.prototype.lo = function () {
return new NdArray(this.selection.lo.apply(this.selection, arguments));
};
/**
* Return a sliced view of the array.
*
* @returns {NdArray}
*
* @example
arr = nj.arange(4*4).reshape(4,4)
// array([[ 0, 1, 2, 3],
// [ 4, 5, 6, 7],
// [ 8, 9, 10, 11],
// [ 12, 13, 14, 15]])
arr.hi(3,3)
// array([[ 0, 1, 2],
// [ 4, 5, 6],
// [ 8, 9, 10]])
arr.lo(1,1).hi(2,2)
// array([[ 5, 6],
// [ 9, 10]])
*/
NdArray.prototype.hi = function () {
return new NdArray(this.selection.hi.apply(this.selection, arguments));
};
NdArray.prototype.step = function () {
return new NdArray(this.selection.step.apply(this.selection, arguments));
};
/**
* Return a copy of the array collapsed into one dimension using row-major order (C-style)
*
* @returns {NdArray}
*/
NdArray.prototype.flatten = function () {
if (this.ndim === 1) { // already flattened
return new NdArray(this.selection);
}
var T = _.getType(this.dtype);
var arr = _.flatten(this.tolist(), true);
if (!(arr instanceof T)) {
arr = new T(arr);
}
return new NdArray(arr, [this.size]);
};
/**
* Gives a new shape to the array without changing its data.
* @param {Array} shape
* @returns {NdArray}
*/
NdArray.prototype.reshape = function (shape) {
if (arguments.length === 0) {
throw new errors.ValueError('function takes at least one argument (0 given)');
}
if (arguments.length === 1 && _.isNumber(shape)) {
shape = [shape];
}
if (arguments.length > 1) {
shape = [].slice.call(arguments);
}
if (this.size !== _.shapeSize(shape)) {
throw new errors.ValueError('total size of new array must be unchanged');
}
var selfShape = this.selection.shape;
var selfOffset = this.selection.offset;
var selfStride = this.selection.stride;
var selfDim = selfShape.length;
var d = shape.length;
var stride;
var offset;
var i;
var sz;
if (selfDim === d) {
var sameShapes = true;
for (i = 0; i < d; ++i) {
if (selfShape[i] !== shape[i]) {
sameShapes = false;
break;
}
}
if (sameShapes) {
return new NdArray(this.selection.data, selfShape, selfStride, selfOffset);
}
} else if (selfDim === 1) {
// 1d view
stride = new Array(d);
for (i = d - 1, sz = 1; i >= 0; --i) {
stride[i] = sz;
sz *= shape[i];
}
offset = selfOffset;
for (i = 0; i < d; ++i) {
if (stride[i] < 0) {
offset -= (shape[i] - 1) * stride[i];
}
}
return new NdArray(this.selection.data, shape, stride, offset);
}
var minDim = Math.min(selfDim, d);
var areCompatible = true;
for (i = 0; i < minDim; i++) {
if (selfShape[i] !== shape[i]) {
areCompatible = false;
break;
}
}
if (areCompatible) {
stride = new Array(d);
for (i = 0; i < d; i++) {
stride[i] = selfStride[i] || 1;
}
offset = selfOffset;
return new NdArray(this.selection.data, shape, stride, offset);
}
return this.flatten().reshape(shape);
};
/**
* Permute the dimensions of the array.
*
* @param {...number} [axes]
* @returns {NfdArray}
*/
NdArray.prototype.transpose = function (axes) {
if (arguments.length === 0) {
var d = this.ndim;
axes = new Array(d);
for (var i = 0; i < d; i++) {
axes[i] = d - i - 1;
}
} else if (arguments.length > 1) {
axes = arguments;
}
return new NdArray(this.selection.transpose.apply(this.selection, axes));
};
/**
* Dot product of two arrays.
*
* @param {(Array|NdArray)} x
* @returns {NdArray}
*/
NdArray.prototype.dot = function (x) {
x = (x instanceof NdArray) ? x : createArray(x, this.dtype);
var tShape = this.shape;
var xShape = x.shape;
if (tShape.length === 2 && xShape.length === 2 && tShape[1] === xShape[0]) { // matrix/matrix
var T = _.getType(this.dtype);
var c = new NdArray(new T(tShape[0] * xShape[1]), [tShape[0], xShape[1]]);
gemm(c.selection, this.selection, x.selection);
return c;
} else if (tShape.length === 1 && xShape.length === 2 && tShape[0] === xShape[0]) { // vector/matrix
return this.reshape([tShape[0], 1]).T.dot(x).reshape(xShape[1]);
} else if (tShape.length === 2 && xShape.length === 1 && tShape[1] === xShape[0]) { // matrix/vector
return this.dot(x.reshape([xShape[0], 1])).reshape(tShape[0]);
} else if (tShape.length === 1 && xShape.length === 1 && tShape[0] === xShape[0]) { // vector/vector
return this.reshape([tShape[0], 1]).T.dot(x.reshape([xShape[0], 1])).reshape([1]);
} else {
throw new errors.ValueError('cannot compute the matrix product of given arrays');
}
};
/**
* Assign `x` to the array, element-wise.
*
* @param {(NdArray|Array|number)} x
* @param {boolean} [copy=true]
* @returns {NdArray}
*/
NdArray.prototype.assign = function (x, copy) {
if (arguments.length === 1) {
copy = true;
}
var arr = copy ? this.clone() : this;
if (_.isNumber(x)) {
ops.assigns(arr.selection, x);
return arr;
}
x = createArray(x, this.dtype);
ops.assign(arr.selection, x.selection);
return arr;
};
/**
* Add `x` to the array, element-wise.
*
* @param {(NdArray|Array|number)} x
* @param {boolean} [copy=true]
* @returns {NdArray}
*/
NdArray.prototype.add = function (x, copy) {
if (arguments.length === 1) {
copy = true;
}
var arr = copy ? this.clone() : this;
if (_.isNumber(x)) {
ops.addseq(arr.selection, x);
return arr;
}
x = createArray(x, this.dtype);
ops.addeq(arr.selection, x.selection);
return arr;
};
/**
* Subtract `x` to the array, element-wise.
*
* @param {(NdArray|Array|number)} x
* @param {boolean} [copy=true]
* @returns {NdArray}
*/
NdArray.prototype.subtract = function (x, copy) {
if (arguments.length === 1) {
copy = true;
}
var arr = copy ? this.clone() : this;
if (_.isNumber(x)) {
ops.subseq(arr.selection, x);
return arr;
}
x = createArray(x, this.dtype);
ops.subeq(arr.selection, x.selection);
return arr;
};
/**
* Multiply array by `x`, element-wise.
*
* @param {(NdArray|Array|number)} x
* @param {boolean} [copy=true]
* @returns {NdArray}
*/
NdArray.prototype.multiply = function (x, copy) {
if (arguments.length === 1) {
copy = true;
}
var arr = copy ? this.clone() : this;
if (_.isNumber(x)) {
ops.mulseq(arr.selection, x);
return arr;
}
x = createArray(x, this.dtype);
ops.muleq(arr.selection, x.selection);
return arr;
};
/**
* Divide array by `x`, element-wise.
*
* @param {(NdArray|Array|number)} x
* @param {boolean} [copy=true]
* @returns {NdArray}
*/
NdArray.prototype.divide = function (x, copy) {
if (arguments.length === 1) {
copy = true;
}
var arr = copy ? this.clone() : this;
if (_.isNumber(x)) {
ops.divseq(arr.selection, x);
return arr;
}
x = createArray(x, this.dtype);
ops.diveq(arr.selection, x.selection);
return arr;
};
/**
* Raise array elements to powers from given array, element-wise.
*
* @param {(NdArray|Array|number)} x
* @param {boolean} [copy=true] - set to false to modify the array rather than create a new one
* @returns {NdArray}
*/
NdArray.prototype.pow = function (x, copy) {
if (arguments.length === 1) { copy = true; }
var arr = copy ? this.clone() : this;
if (_.isNumber(x)) {
ops.powseq(arr.selection, x);
return arr;
}
x = createArray(x, this.dtype);
ops.poweq(arr.selection, x.selection);
return arr;
};
/**
* Calculate the exponential of all elements in the array, element-wise.
*
* @param {boolean} [copy=true] - set to false to modify the array rather than create a new one
* @returns {NdArray}
*/
NdArray.prototype.exp = function (copy) {
if (arguments.length === 0) { copy = true; }
var arr = copy ? this.clone() : this;
ops.expeq(arr.selection);
return arr;
};
/**
* Calculate the positive square-root of all elements in the array, element-wise.
*
* @param {boolean} [copy=true] - set to false to modify the array rather than create a new one
* @returns {NdArray}
*/
NdArray.prototype.sqrt = function (copy) {
if (arguments.length === 0) { copy = true; }
var arr = copy ? this.clone() : this;
ops.sqrteq(arr.selection);
return arr;
};
/**
* Return the maximum value of the array
*
* @returns {Number}
*/
NdArray.prototype.max = function () {
if (this.selection.size === 0) {
return null;
}
return ops.sup(this.selection);
};
/**
* Return the minimum value of the array
*
* @returns {Number}
*/
NdArray.prototype.min = function () {
if (this.selection.size === 0) {
return null;
}
return ops.inf(this.selection);
};
/**
* Sum of array elements.
*
* @returns {number}
*/
NdArray.prototype.sum = function () {
return ops.sum(this.selection);
};
/**
* Returns the standard deviation, a measure of the spread of a distribution, of the array elements.
*
* @returns {number}
*/
NdArray.prototype.std = function () {
var squares = this.clone();
ops.powseq(squares.selection, 2);
var mean = this.mean();
var variance = Math.abs(ops.sum(squares.selection) / _.shapeSize(this.shape) - mean * mean);
return variance > 0 ? Math.sqrt(variance) : 0;
};
/**
* Return the arithmetic mean of array elements.
*
* @returns {number}
*/
NdArray.prototype.mean = function () {
return ops.sum(this.selection) / _.shapeSize(this.shape);
};
/**
* Converts {NdArray} to a native JavaScript {Array}
*
* @returns {Array}
*/
NdArray.prototype.tolist = function () {
return unpackArray(this.selection);
};
NdArray.prototype.valueOf = function () {
return this.tolist();
};
/**
* Stringify the array to make it readable by a human.
*
* @returns {string}
*/
NdArray.prototype.toString = function () {
var nChars = formatNumber(this.max()).length;
var reg1 = /\]\,(\s*)\[/g;
var spacer1 = '],\n$1 [';
var reg3 = /\]\,(\s+)...\,(\s+)\[/g;
var spacer3 = '],\n$2 ...\n$2 [';
var reg2 = /\[\s+\[/g;
var spacer2 = '[[';
function formatArray (k, v) {
if (_.isString(v)) { return v; }
if (_.isNumber(v)) {
var s = formatNumber(v);
return new Array(Math.max(0, nChars - s.length + 2)).join(' ') + s;
}
k = k || 0;
var arr;
var th = CONF.printThreshold;
var hth = th / 2 | 0;
if (v.length > th) {
arr = [].concat(v.slice(0, hth), [' ...'], v.slice(v.length - hth));
} else {
arr = v;
}
return new Array(k + 1).join(' ') + '[' + arr.map(function (i, ii) {
return formatArray(ii === 0 && k === 0 ? 1 : k + 1, i);
}).join(',') + ']';
}
var base = JSON
.stringify(this.tolist(), formatArray)
.replace(reg1, spacer1)
.replace(reg2, spacer2)
.replace(reg2, spacer2)
.replace(reg3, spacer3)
.slice(2, -1);
switch (this.dtype) {
case 'array':
return 'array([' + base + ')';
default:
return 'array([' + base + ', dtype=' + this.dtype + ')';
}
};
/**
* Stringify the array to make it readable in the console, by a human.
*
* @returns {string}
*/
NdArray.prototype.inspect = NdArray.prototype.toString;
/**
* Stringify object to JSON
* @returns {*}
*/
NdArray.prototype.toJSON = function () {
return JSON.stringify(this.tolist());
};
/**
* Create a full copy of the array
*
* @returns {NdArray}
*/
NdArray.prototype.clone = function () {
var s = this.selection;
if (typeof s.data.slice === 'undefined') {
return new NdArray(ndarray([].slice.apply(s.data), s.shape, s.stride, s.offset)); // for legacy browsers
}
return new NdArray(ndarray(s.data.slice(), s.shape, s.stride, s.offset));
};
/**
* Return true if two arrays have the same shape and elements, false otherwise.
* @param {(Array|NdArray)} array
* @returns {boolean}
*/
NdArray.prototype.equal = function (array) {
array = createArray(array);
if (this.size !== array.size || this.ndim !== array.ndim) {
return false;
}
var d = this.ndim;
for (var i = 0; i < d; i++) {
if (this.shape[i] !== array.shape[i]) {
return false;
}
}
return ops.all(ops.eqeq(this.selection, array.selection));
};
/**
* Round array to the to the nearest integer.
*
* @param {boolean} [copy=true]
* @returns {NdArray}
*/
NdArray.prototype.round = function (copy) {
if (arguments.length === 0) {
copy = true;
}
var arr = copy ? this.clone() : this;
ops.roundeq(arr.selection);
return arr;
};
/**
* Return the inverse of the array, element-wise.
*
* @returns {NdArray}
*/
NdArray.prototype.negative = function () {
var c = this.clone();
ops.neg(c.selection, this.selection);
return c;
};
NdArray.prototype.iteraxis = function (axis, cb) {
var shape = this.shape;
if (axis === -1) {
axis = shape.length - 1;
}
if (axis < 0 || axis > shape.length - 1) {
throw new errors.ValueError('invalid axis');
}
for (var i = 0; i < shape[axis]; i++) {
var loc = new Array(axis + 1);
for (var ii = 0; ii < axis + 1; ii++) {
loc[ii] = (ii === axis) ? i : null;
}
var subArr = this.selection.pick.apply(this.selection, loc);
var xi = createArray(unpackArray(subArr), this.dtype);
cb(xi, i);
}
};
var doConjMuleq = require('cwise/lib/wrapper')({"args":["array","array","array","array"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{var _inline_55_c=_inline_55_arg2_,_inline_55_f=_inline_55_arg3_,_inline_55_i=_inline_55_arg0_,_inline_55_o=_inline_55_arg1_,_inline_55_t=_inline_55_i*(_inline_55_c+_inline_55_f);_inline_55_arg0_=_inline_55_t-_inline_55_f*(_inline_55_i+_inline_55_o),_inline_55_arg1_=_inline_55_t+_inline_55_c*(_inline_55_o-_inline_55_i)}","args":[{"name":"_inline_55_arg0_","lvalue":true,"rvalue":true,"count":2},{"name":"_inline_55_arg1_","lvalue":true,"rvalue":true,"count":2},{"name":"_inline_55_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_55_arg3_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":["_inline_55_c","_inline_55_f","_inline_55_i","_inline_55_o","_inline_55_t"]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"cwise","blockSize":64});
var doConvolve3x3 = require('cwise/lib/wrapper')({"args":["array","array","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar",{"offset":[-1,-1],"array":1},{"offset":[-1,0],"array":1},{"offset":[-1,1],"array":1},{"offset":[0,-1],"array":1},{"offset":[0,1],"array":1},{"offset":[1,-1],"array":1},{"offset":[1,0],"array":1},{"offset":[1,1],"array":1}],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_58_arg0_=_inline_58_arg11_*_inline_58_arg10_+_inline_58_arg12_*_inline_58_arg9_+_inline_58_arg13_*_inline_58_arg8_+_inline_58_arg14_*_inline_58_arg7_+_inline_58_arg1_*_inline_58_arg6_+_inline_58_arg15_*_inline_58_arg5_+_inline_58_arg16_*_inline_58_arg4_+_inline_58_arg17_*_inline_58_arg3_+_inline_58_arg18_*_inline_58_arg2_}","args":[{"name":"_inline_58_arg0_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_58_arg1_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg4_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg5_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg6_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg7_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg8_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg9_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg10_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg11_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg12_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg13_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg14_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg15_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg16_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg17_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_58_arg18_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"cwise","blockSize":64});
var doConvolve5x5 = require('cwise/lib/wrapper')({"args":["index","array","array","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar","scalar",{"offset":[-2,-2],"array":1},{"offset":[-2,-1],"array":1},{"offset":[-2,0],"array":1},{"offset":[-2,1],"array":1},{"offset":[-2,2],"array":1},{"offset":[-1,-2],"array":1},{"offset":[-1,-1],"array":1},{"offset":[-1,0],"array":1},{"offset":[-1,1],"array":1},{"offset":[-1,2],"array":1},{"offset":[0,-2],"array":1},{"offset":[0,-1],"array":1},{"offset":[0,1],"array":1},{"offset":[0,2],"array":1},{"offset":[1,-2],"array":1},{"offset":[1,-1],"array":1},{"offset":[1,0],"array":1},{"offset":[1,1],"array":1},{"offset":[1,2],"array":1},{"offset":[2,-2],"array":1},{"offset":[2,-1],"array":1},{"offset":[2,0],"array":1},{"offset":[2,1],"array":1},{"offset":[2,2],"array":1}],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_61_arg1_=_inline_61_arg0_[0]<2||_inline_61_arg0_[1]<2?0:_inline_61_arg28_*_inline_61_arg27_+_inline_61_arg29_*_inline_61_arg26_+_inline_61_arg30_*_inline_61_arg25_+_inline_61_arg31_*_inline_61_arg24_+_inline_61_arg32_*_inline_61_arg23_+_inline_61_arg33_*_inline_61_arg22_+_inline_61_arg34_*_inline_61_arg21_+_inline_61_arg35_*_inline_61_arg20_+_inline_61_arg36_*_inline_61_arg19_+_inline_61_arg37_*_inline_61_arg18_+_inline_61_arg38_*_inline_61_arg17_+_inline_61_arg39_*_inline_61_arg16_+_inline_61_arg2_*_inline_61_arg15_+_inline_61_arg40_*_inline_61_arg14_+_inline_61_arg41_*_inline_61_arg13_+_inline_61_arg42_*_inline_61_arg12_+_inline_61_arg43_*_inline_61_arg11_+_inline_61_arg44_*_inline_61_arg10_+_inline_61_arg45_*_inline_61_arg9_+_inline_61_arg46_*_inline_61_arg8_+_inline_61_arg47_*_inline_61_arg7_+_inline_61_arg48_*_inline_61_arg6_+_inline_61_arg49_*_inline_61_arg5_+_inline_61_arg50_*_inline_61_arg4_+_inline_61_arg51_*_inline_61_arg3_}","args":[{"name":"_inline_61_arg0_","lvalue":false,"rvalue":true,"count":2},{"name":"_inline_61_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_61_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg4_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg5_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg6_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg7_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg8_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg9_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg10_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg11_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg12_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg13_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg14_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg15_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg16_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg17_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg18_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg19_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg20_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg21_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg22_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg23_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg24_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg25_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg26_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg27_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg28_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg29_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg30_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg31_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg32_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg33_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg34_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg35_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg36_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg37_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg38_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg39_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg40_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg41_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg42_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg43_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg44_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg45_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg46_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg47_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg48_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg49_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg50_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_61_arg51_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"cwise","blockSize":64});
/**
* Returns the discrete, linear convolution of the array using the given filter.
*
* @note: Arrays must have the same dimensions and `filter` must be smaller than the array.
* @note: The convolution product is only given for points where the signals overlap completely. Values outside the signal boundary have no effect. This behaviour is known as the 'valid' mode.
* @note: Use optimized code for 3x3, 3x3x1, 5x5, 5x5x1 filters, FFT otherwise.
*
* @param {Array|NdArray} filter
*/
NdArray.prototype.convolve = function (filter) {
filter = NdArray.new(filter);
var ndim = this.ndim;
if (ndim !== filter.ndim) {
throw new errors.ValueError('arrays must have the same dimensions');
}
var outShape = new Array(ndim);
var step = new Array(ndim);
var ts = this.selection;
var tShape = this.shape;
var fs = filter.selection;
var fShape = filter.shape;
for (var i = 0; i < ndim; i++) {
var l = tShape[i] - fShape[i] + 1;
if (l < 0) {
throw new errors.ValueError('filter cannot be greater than the array');
}
outShape[i] = l;
step[i] = -1;
}
if (ndim === 2 && fShape[0] === 3 && fShape[1] === 3) {
var out3x3 = new NdArray(new Float32Array(_.shapeSize(tShape)), tShape);
doConvolve3x3(
out3x3.selection, // c
ts, // x
fs.get(0, 0), // fa
fs.get(0, 1), // fb
fs.get(0, 2), // fc
fs.get(1, 0), // fd
fs.get(1, 1), // fe
fs.get(1, 2), // ff
fs.get(2, 0), // fg
fs.get(2, 1), // fh
fs.get(2, 2) // fi
);
return out3x3.lo(1, 1).hi(outShape[0], outShape[1]);
} else if (ndim === 3 && fShape[2] === 1 && tShape[2] === 1 && fShape[0] === 3 && fShape[1] === 3) {
var out3x3x1 = new NdArray(new Float32Array(_.shapeSize(tShape)), tShape);
doConvolve3x3(
out3x3x1.selection.pick(null, null, 0), // c
ts.pick(null, null, 0), // x
fs.get(0, 0, 0), // fa
fs.get(0, 1, 0), // fb
fs.get(0, 2, 0), // fc
fs.get(1, 0, 0), // fd
fs.get(1, 1, 0), // fe
fs.get(1, 2, 0), // ff
fs.get(2, 0, 0), // fg
fs.get(2, 1, 0), // fh
fs.get(2, 2, 0) // fi
);
return out3x3x1.lo(1, 1).hi(outShape[0], outShape[1]);
} else if (ndim === 2 && fShape[0] === 5 && fShape[1] === 5) {
var out5x5 = new NdArray(new Float32Array(_.shapeSize(tShape)), tShape);
doConvolve5x5(
out5x5.selection, // c
ts, // x
fs.get(0, 0), // fa
fs.get(0, 1), // fb
fs.get(0, 2), // fc
fs.get(0, 3), // fd
fs.get(0, 4), // fe
fs.get(1, 0), // ff
fs.get(1, 1), // fg
fs.get(1, 2), // fh
fs.get(1, 3), // fi
fs.get(1, 4), // fj
fs.get(2, 0), // fk
fs.get(2, 1), // fl
fs.get(2, 2), // fm
fs.get(2, 3), // fn
fs.get(2, 4), // fo
fs.get(3, 0), // fp
fs.get(3, 1), // fq
fs.get(3, 2), // fr
fs.get(3, 3), // fs
fs.get(3, 4), // ft
fs.get(4, 0), // fu
fs.get(4, 1), // fv
fs.get(4, 2), // fw
fs.get(4, 3), // fx
fs.get(4, 4) // fy
);
return out5x5.lo(2, 2).hi(outShape[0], outShape[1]);
} else if (ndim === 3 && fShape[2] === 1 && tShape[2] === 1 && fShape[0] === 5 && fShape[1] === 5) {
var out5x5x1 = new NdArray(new Float32Array(_.shapeSize(tShape)), tShape);
doConvolve5x5(
out5x5x1.selection, // c
ts, // x
fs.get(0, 0, 0), // fa
fs.get(0, 1, 0), // fb
fs.get(0, 2, 0), // fc
fs.get(0, 3, 0), // fd
fs.get(0, 4, 0), // fe
fs.get(1, 0, 0), // ff
fs.get(1, 1, 0), // fg
fs.get(1, 2, 0), // fh
fs.get(1, 3, 0), // fi
fs.get(1, 4, 0), // fj
fs.get(2, 0, 0), // fk
fs.get(2, 1, 0), // fl
fs.get(2, 2, 0), // fm
fs.get(2, 3, 0), // fn
fs.get(2, 4, 0), // fo
fs.get(3, 0, 0), // fp
fs.get(3, 1, 0), // fq
fs.get(3, 2, 0), // fr
fs.get(3, 3, 0), // fs
fs.get(3, 4, 0), // ft
fs.get(4, 0, 0), // fu
fs.get(4, 1, 0), // fv
fs.get(4, 2, 0), // fw
fs.get(4, 3, 0), // fx
fs.get(4, 4, 0) // fy
);
return out5x5x1.lo(2, 2).hi(outShape[0], outShape[1]);
} else {
return this.fftconvolve(filter);
}
};
NdArray.prototype.fftconvolve = function (filter) {
filter = NdArray.new(filter);
if (this.ndim !== filter.ndim) {
throw new errors.ValueError('arrays must have the same dimensions');
}
var as = this.selection;
var bs = filter.selection;
var d = this.ndim;
var nsize = 1;
var nstride = new Array(d);
var nshape = new Array(d);
var oshape = new Array(d);
var i;
for (i = d - 1; i >= 0; --i) {
nshape[i] = as.shape[i];
nstride[i] = nsize;
nsize *= nshape[i];
oshape[i] = as.shape[i] - bs.shape[i] + 1;
}
var T = _.getType(as.dtype);
var out = new NdArray(new T(_.shapeSize(oshape)), oshape);
var outs = out.selection;
var xT = ndPool.mallocDouble(nsize);
var x = ndarray(xT, nshape, nstride, 0);
ops.assigns(x, 0);
ops.assign(x.hi.apply(x, as.shape), as);
var yT = ndPool.mallocDouble(nsize);
var y = ndarray(yT, nshape, nstride, 0);
ops.assigns(y, 0);
// FFT x/y
ndFFT(1, x, y);
var uT = ndPool.mallocDouble(nsize);
var u = ndarray(uT, nshape, nstride, 0);
ops.assigns(u, 0);
ops.assign(u.hi.apply(u, bs.shape), bs);
var vT = ndPool.mallocDouble(nsize);
var v = ndarray(vT, nshape, nstride, 0);
ops.assigns(v, 0);
ndFFT(1, u, v);
doConjMuleq(x, y, u, v);
ndFFT(-1, x, y);
var outShape = new Array(d);
var outOffset = new Array(d);
var needZeroFill = false;
for (i = 0; i < d; ++i) {
if (outs.shape[i] > nshape[i]) {
needZeroFill = true;
}
outOffset[i] = bs.shape[i] - 1;
outShape[i] = Math.min(outs.shape[i], nshape[i] - outOffset[i]);
}
var croppedX;
if (needZeroFill) {
ops.assign(outs, 0.0);
}
croppedX = x.lo.apply(x, outOffset);
croppedX = croppedX.hi.apply(croppedX, outShape);
ops.assign(outs.hi.apply(outs, outShape), croppedX);
ndPool.freeDouble(xT);
ndPool.freeDouble(yT);
ndPool.freeDouble(uT);
ndPool.freeDouble(vT);
return out;
};
function createArray (arr, dtype) {
if (arr instanceof NdArray) { return arr; }
var T = _.getType(dtype);
if (_.isNumber(arr)) {
if (T !== Array) {
return new NdArray(new T([arr]), [1]);
} else {
return new NdArray([arr], [1]);
}
}
var shape = _.getShape(arr);
if (shape.length > 1) {
arr = _.flatten(arr, true);
}
if (!(arr instanceof T)) {
arr = new T(arr);
}
return new NdArray(arr, shape);
}
NdArray.new = createArray;
module.exports = NdArray;
/* utils */
function initNativeArray (shape, i) {
i = i || 0;
var c = shape[i] | 0;
if (c <= 0) { return []; }
var result = new Array(c);
var j;
if (i === shape.length - 1) {
for (j = 0; j < c; ++j) {
result[j] = 0;
}
} else {
for (j = 0; j < c; ++j) {
result[j] = initNativeArray(shape, i + 1);
}
}
return result;
}
var doUnpack = require('cwise/lib/wrapper')({"args":["array","scalar","index"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{var _inline_64_a,_inline_64_e=_inline_64_arg1_;for(_inline_64_a=0;_inline_64_a<_inline_64_arg2_.length-1;++_inline_64_a)_inline_64_e=_inline_64_e[_inline_64_arg2_[_inline_64_a]];_inline_64_e[_inline_64_arg2_[_inline_64_arg2_.length-1]]=_inline_64_arg0_}","args":[{"name":"_inline_64_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_64_arg1_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_64_arg2_","lvalue":false,"rvalue":true,"count":4}],"thisVars":[],"localVars":["_inline_64_a","_inline_64_e"]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"unpackCwise","blockSize":64});
function unpackArray (arr) {
var result = initNativeArray(arr.shape, 0);
doUnpack(arr, result);
return result;
}
function formatNumber (v) {
return String(Number((v || 0).toFixed(CONF.nFloatingValues)));
}
},{"./config":23,"./errors":25,"./utils":43,"cwise/lib/wrapper":8,"ndarray":18,"ndarray-fft":13,"ndarray-gemm":15,"ndarray-ops":17,"typedarray-pool":21}],43:[function(require,module,exports){
'use strict';
var DTYPES = require('./dtypes');
function isNumber (value) {
return typeof value === 'number';
}
function isString (value) {
return typeof value === 'string';
}
function isFunction (value) {
return typeof value === 'function';
}
function baseFlatten (array, isDeep, result) {
result = result || [];
var index = -1;
var length = array.length;
while (++index < length) {
var value = array[index];
if (isNumber(value)) {
result[result.length] = value;
} else if (isDeep) {
// Recursively flatten arrays (susceptible to call stack limits).
baseFlatten(value, isDeep, result);
} else {
result.push(value);
}
}
return result;
}
function shapeSize (shape) {
var s = 1;
for (var i = 0; i < shape.length; i++) {
s *= shape[i];
}
return s;
}
function getType (dtype) {
return isFunction(dtype) ? dtype : (DTYPES[dtype] || Array);
}
function _dim (x) {
var ret = [];
while (typeof x === 'object') { ret.push(x.length); x = x[0]; }
return ret;
}
function getShape (array) {
var y, z;
if (typeof array === 'object') {
y = array[0];
if (typeof y === 'object') {
z = y[0];
if (typeof z === 'object') {
return _dim(array);
}
return [array.length, y.length];
}
return [array.length];
}
return [];
}
// function haveSameShape (shape1, shape2) {
// if (shapeSize(shape1) !== shapeSize(shape2) || shape1.length !== shape2.length) {
// return false;
// }
// var d = shape1.length;
// for (var i = 0; i < d; i++) {
// if (shape1[i] !== shape2[i]) {
// return false;
// }
// }
// return true;
// }
module.exports = {
isNumber: isNumber,
isString: isString,
isFunction: isFunction,
flatten: baseFlatten,
shapeSize: shapeSize,
getType: getType,
getShape: getShape
};
},{"./dtypes":24}]},{},[41])(41)
});
This file has been truncated, but you can view the full file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment