├── .gitignore ├── README.md ├── js ├── containers.js ├── conv.js ├── env.js ├── full.js ├── init.js ├── loaders.js ├── pointwise.js ├── pool.js └── utils.js ├── nn.js ├── package.json ├── static ├── index.html └── js │ ├── benchmark.js │ └── nn.js └── test ├── data.lua ├── data ├── conv.json ├── full.json └── pool.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | js/*~ 3 | test/*~ 4 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nn.js : high performance (not yet) neural networks for the Browser 2 | 3 | ## This package is in all respects inferior to [convnet.js](http://cs.stanford.edu/people/karpathy/convnetjs/) 4 | 5 | This package is not meant to replace the excellent [convnet.js](http://cs.stanford.edu/people/karpathy/convnetjs/), 6 | but provide a lower-level package. 7 | 8 | **A fast low-level javascript package for multi-threaded neural net layers for the browser.** 9 | 10 | 11 | For now, this package only implements the **forward** ops, and does not implement backward. 12 | 13 | It is useful when porting Torch models to the browser. 14 | 15 | For example, it powers the browser demo in: [http://soumith.ch/eyescream](http://soumith.ch/eyescream) 16 | 17 | ### Layers: 18 | ``` 19 | nn.SpatialConvolution(weight, bias, padH, padW) 20 | nn.SpatialMaxPooling(kH, kW, dH, dW) 21 | nn.ReLU() 22 | nn.Linear(weight, bias) 23 | nn.View(shape) 24 | nn.Sequential() 25 | nn.JoinTable(dim) 26 | nn.ParallelTable() 27 | nn.Identity() 28 | ``` 29 | 30 | ###Uses: 31 | 32 | - [TODO] Web workers for using multiple cores 33 | - [TODO] SIMD optimizations if the browser supports [SIMD.js](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SIMD#Browser_compatibility) or [WebAssembly](https://github.com/WebAssembly/design/blob/master/README.md) 34 | 35 | 36 | ###Dependencies: 37 | 38 | - ndarray 39 | - ndarray-fill 40 | - msgpack-js 41 | 42 | ###Unit tests: 43 | 44 | Unit tests can be run via nodejs. 45 | ``` bash 46 | $ npm -g install mocha 47 | $ cd nnjs 48 | $ mocha 49 | 50 | SpatialConvolution 51 | ✓ Should compare against torch convolutions (126ms) 52 | 53 | SpatialMaxPooling 54 | ✓ Should compare against torch SpatialMaxPooling 55 | 56 | Linear 57 | ✓ Should compare against torch Linear layer 58 | 59 | Loader 60 | ✓ Should load a full multi-layer model and compare against torch result (3051ms) 61 | 62 | 63 | 4 passing (3s) 64 | ``` 65 | 66 | 67 | ### Building for the browser 68 | ``` bash 69 | npm install -g browserify 70 | browserify -r ./js/init.js:nn -r ndarray -r ndarray-fill -o static/js/nn.js 71 | ``` 72 | -------------------------------------------------------------------------------- /js/containers.js: -------------------------------------------------------------------------------- 1 | var env = require('./env.js') 2 | var ndarray = require("ndarray") 3 | 4 | function Sequential() { 5 | this.modules = []; 6 | } 7 | 8 | Sequential.prototype.add = function(m) { 9 | this.modules.push(m); 10 | } 11 | 12 | Sequential.prototype.forward = function(input) { 13 | var output = input; 14 | for (var i = 0; i < this.modules.length; i++) { 15 | output = this.modules[i].forward(output); 16 | } 17 | return output; 18 | } 19 | 20 | env.Sequential = Sequential 21 | 22 | //////////////////////////////////////////////////////////// 23 | 24 | function ParallelTable() { 25 | this.modules = []; 26 | } 27 | 28 | ParallelTable.prototype.add = function(m) { 29 | this.modules.push(m); 30 | } 31 | 32 | ParallelTable.prototype.forward = function(input) { 33 | var output = []; 34 | for (var i=0; i < this.modules.length; i++) { 35 | output.push(this.modules[i].forward(input[i])); 36 | } 37 | return output; 38 | } 39 | 40 | env.ParallelTable = ParallelTable 41 | 42 | //////////////////////////////////////////////////////////// 43 | 44 | function JoinTable(dim) { 45 | this.dim = dim; 46 | } 47 | 48 | JoinTable.prototype.forward = function(input) { 49 | var size = 0; 50 | for (var i=0; i < input.length; i++) { 51 | size += input[i].shape[this.dim-1]; 52 | } 53 | var outShape = []; 54 | for (var i=0; i < input[0].shape.length; i++) { 55 | outShape[i] = input[0].shape[i]; 56 | } 57 | outShape[this.dim-1] = size; 58 | var footprint = 1; 59 | for (var i=0; i < outShape.length; i++) { 60 | footprint = footprint * outShape[i] 61 | } 62 | 63 | var output = ndarray(new Float32Array(footprint), outShape); 64 | if (this.dim == 1) { 65 | var idx = 0; 66 | for (var j=0; j < input.length; j++) { 67 | var inp = input[j].data; 68 | for (var i=0; i < inp.length; i++) { 69 | output.data[idx++] = inp[i]; 70 | } 71 | } 72 | } else if (this.dim == 3) { 73 | for (var i=0; i < outShape[0]; i++) { 74 | for (var j=0; j < outShape[1]; j++) { 75 | var idx = 0; 76 | for (var k=0; k < input.length; k++) { 77 | var inp = input[k]; 78 | var sz = inp.shape[this.dim-1]; 79 | for (var t=0; t < sz; t++) { 80 | output.set(i, j, idx + t, inp.get(i, j, t)) 81 | } 82 | idx = idx + sz; 83 | } 84 | } 85 | } 86 | } else { 87 | throw('Unsupported dim: ' + this.dim); 88 | } 89 | return output; 90 | } 91 | 92 | env.JoinTable = JoinTable 93 | -------------------------------------------------------------------------------- /js/conv.js: -------------------------------------------------------------------------------- 1 | var env = require('./env.js') 2 | var ndarray = require("ndarray") 3 | var fill = require("ndarray-fill") 4 | 5 | /* weight is a 4D ndarray with dimensions 6 | [nOutputPlane, kH, kW, nInputPlane] 7 | 8 | bias is a 1D ndarray with dimensions 9 | [nOutputPlane] */ 10 | function SpatialConvolution(weight, bias, padH, padW) { 11 | this.weight = weight; 12 | this.bias = bias; 13 | this.nOutputPlane = weight.shape[0]; 14 | this.nInputPlane = weight.shape[1]; 15 | this.kH = weight.shape[2]; 16 | this.kW = weight.shape[3]; 17 | this.padH = padH 18 | this.padW = padW 19 | } 20 | 21 | SpatialConvolution.prototype.forward = function(input) { 22 | var nOutputPlane = this.nOutputPlane |0; 23 | var nInputPlane = input.shape[0] |0; 24 | var iH = input.shape[1] |0; 25 | var iW = input.shape[2] |0; 26 | var oH = (iH + this.padH*2 - this.kH + 1) |0; 27 | var oW = (iW + this.padW*2 - this.kW + 1) |0; 28 | var kH = this.kH |0; 29 | var kW = this.kW |0; 30 | var weight = this.weight; 31 | var bias = this.bias; 32 | var padH = this.padH |0; 33 | var padW = this.padW |0; 34 | var output = ndarray(new Float32Array(nOutputPlane * oH * oW), 35 | [nOutputPlane, oH, oW]); 36 | 37 | /* fill with bias */ 38 | for (var i = 0; i < bias.shape[0]; i++) { 39 | var channel = output.pick(i, null, null); 40 | fill(channel, function(k,j) { 41 | return bias.get(i) 42 | }) 43 | } 44 | 45 | /* do convolutions */ 46 | for(var i = 0; i < nOutputPlane; i++) { 47 | var oChan = i * (oH * oW); // select the output feature map 48 | var wOChan = i * (nInputPlane * kH * kW); // select the weight cube for this feature map 49 | for(var j = 0; j < nInputPlane; j++) { 50 | var wOIChan = wOChan + j * (kH * kW); // select the weight kernel for this (output,input) map pair 51 | var iChan = j * (iH * iW); /* get input */ 52 | /* regular convolution */ 53 | var posH = -padH; 54 | var posW = -padW; 55 | for(var yy = 0; yy < oH; yy++) { 56 | var oHPtr = oChan + yy * oW; 57 | for(var xx = 0; xx < oW; xx++) { 58 | /* Dot product in two dimensions...(between input image and the mask) */ 59 | var oPtr = oHPtr + xx; 60 | var sum = output.data[oPtr] 61 | for(var ky = 0; ky < kH; ky++) { 62 | if (posH+ky >= 0 && posH+ky < iH) { 63 | var iHPtr = iChan + ((posH + ky) * iW); 64 | var wHPtr = wOIChan + ky * kW; 65 | for(var kx = 0; kx < kW; kx++) { 66 | if(posW+kx >= 0 && posW+kx < iW) { 67 | sum += input.data[iHPtr + posW + kx] 68 | * weight.data[wHPtr + kx] 69 | } 70 | } 71 | } 72 | } 73 | /* Update output */ 74 | output.data[oPtr] = sum; 75 | posW++; 76 | } 77 | posH++; 78 | posW = -padW; 79 | } 80 | } 81 | } 82 | return output 83 | } 84 | 85 | env.SpatialConvolution = SpatialConvolution 86 | -------------------------------------------------------------------------------- /js/env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | } 3 | -------------------------------------------------------------------------------- /js/full.js: -------------------------------------------------------------------------------- 1 | var env = require('./env.js') 2 | var ndarray = require("ndarray") 3 | var fill = require("ndarray-fill") 4 | 5 | /* weight is a 2D ndarray with dimensions 6 | [outSize, inpSize] 7 | 8 | bias is a 1D ndarray with dimensions 9 | [outSize] */ 10 | function Linear(weight, bias) { 11 | this.weight = weight; 12 | this.bias = bias; 13 | } 14 | 15 | Linear.prototype.forward = function(input) { 16 | var outSize = this.weight.shape[0]; 17 | var inSize = this.weight.shape[1]; 18 | var weight = this.weight; 19 | var bias = this.bias; 20 | var output = ndarray(new Float32Array(outSize), [outSize]); 21 | 22 | for (var i=0; i < outSize; i++) { 23 | var o = bias.get(i); 24 | for (var j=0; j < inSize; j++) { 25 | o += input.data[j] * weight.data[i * inSize + j]; 26 | } 27 | output.set(i, o); 28 | } 29 | return output 30 | } 31 | 32 | env.Linear = Linear 33 | -------------------------------------------------------------------------------- /js/init.js: -------------------------------------------------------------------------------- 1 | var env = require('./env.js') 2 | 3 | require('./conv.js') 4 | require('./pool.js') 5 | require('./full.js') 6 | require('./pointwise.js') 7 | require('./containers.js') 8 | require('./loaders.js') 9 | require('./utils.js') 10 | 11 | module.exports = env 12 | -------------------------------------------------------------------------------- /js/loaders.js: -------------------------------------------------------------------------------- 1 | var env = require('./env.js') 2 | var ndarray = require("ndarray") 3 | var assert = require('assert'); 4 | 5 | 6 | function loadFromObject(inp) { 7 | if (inp.type == 'Sequential') { 8 | var out = new env.Sequential() 9 | for (var i=0; i < inp.modules.length; i++) { 10 | out.add(loadFromObject(inp.modules[i])); 11 | } 12 | return out; 13 | } else if (inp.type == 'ParallelTable') { 14 | var out = new env.ParallelTable() 15 | for (var i=0; i < inp.modules.length; i++) { 16 | out.add(loadFromObject(inp.modules[i])); 17 | } 18 | return out; 19 | } else if (inp.type == 'JoinTable') { 20 | return new env.JoinTable(inp.dimension) 21 | } else if (inp.type == 'Identity') { 22 | return new env.Identity() 23 | } else if (inp.type == 'Linear') { 24 | var weight = new ndarray(inp.weight, 25 | [inp.outSize, inp.inSize]); 26 | var bias = new ndarray(inp.bias, [inp.outSize]) 27 | return new env.Linear(weight, bias) 28 | } else if (inp.type == 'ReLU') { 29 | return new env.ReLU() 30 | } else if (inp.type == 'View') { 31 | return new env.View(inp.dims) 32 | } else if (inp.type == 'SpatialConvolution') { 33 | var weight = new ndarray(inp.weight, 34 | [inp.nOutputPlane, inp.nInputPlane, 35 | inp.kH, inp.kW]); 36 | var bias = new ndarray(inp.bias, [inp.nOutputPlane]) 37 | return new env.SpatialConvolution(weight, bias, 38 | inp.padH, inp.padW) 39 | } else { 40 | throw('Error: Unknown module: ' + inp.type); 41 | } 42 | } 43 | 44 | function loadFromJSON(inp) { 45 | var input = JSON.parse(inp); 46 | return loadFromObject(input); 47 | } 48 | 49 | var msgpack = require('msgpack-js'); 50 | function loadFromMsgPack(input) { 51 | var output = msgpack.decode(input); 52 | return loadFromObject(output); 53 | } 54 | 55 | // var pako = require('pako'); 56 | // function loadFromGZipMsgPack(input) { 57 | // var output = pako.deflate(input); 58 | // return loadFromMsgPack(output); 59 | // } 60 | 61 | // function loadFromGZipJSON(input) { 62 | // var output = pako.deflate(input); 63 | // return loadFromJSON(output); 64 | // } 65 | 66 | env.loadFromJSON = loadFromJSON 67 | env.loadFromMsgPack = loadFromMsgPack 68 | 69 | // env.loadFromGZipMsgPack = loadFromGZipMsgPack 70 | // env.loadFromGZipJSON = loadFromGZipJSON 71 | -------------------------------------------------------------------------------- /js/pointwise.js: -------------------------------------------------------------------------------- 1 | var env = require('./env.js') 2 | var ndarray = require("ndarray") 3 | 4 | function ReLU() {} 5 | 6 | /* in-place ReLU */ 7 | ReLU.prototype.forward = function(input) { 8 | var d = input.data; 9 | for (var i=0; i < d.length; i++) { 10 | if (d[i] < 0) { 11 | d[i] = 0 12 | } 13 | } 14 | return input 15 | } 16 | 17 | env.ReLU = ReLU 18 | 19 | //////////////////////////////////////////////////////// 20 | 21 | function View(shape) { 22 | this.shape = shape; 23 | } 24 | 25 | View.prototype.forward = function(input) { 26 | var output = new ndarray(input.data, this.shape) 27 | return output 28 | } 29 | 30 | env.View = View 31 | 32 | //////////////////////////////////////////////////////// 33 | 34 | function Identity() {} 35 | 36 | Identity.prototype.forward = function(input) { 37 | return input 38 | } 39 | 40 | env.Identity = Identity 41 | ///////////////////////////////////////////////////////// 42 | 43 | function DHWtoHWD() { 44 | } 45 | 46 | DHWtoHWD.prototype.forward = function(input) { 47 | if (input.shape.length != 3) { 48 | throw('Not supported dims') 49 | } 50 | var outShape = []; 51 | var footprint = 1; 52 | outShape[0] = input.shape[1]; 53 | outShape[1] = input.shape[2]; 54 | outShape[2] = input.shape[0]; 55 | for (i=0; i < input.shape.length; i++) { 56 | footprint = footprint * input.shape[i]; 57 | } 58 | var output = new ndarray(new Float32Array(footprint), outShape); 59 | for (i=0; i < outShape[0]; i++) { 60 | for (j=0; j < outShape[1]; j++) { 61 | for (k=0; k < outShape[2]; k++) { 62 | output.set(i, j, k, input.get(k, i, j)) 63 | } 64 | } 65 | } 66 | return output 67 | } 68 | env.DHWtoHWD = DHWtoHWD 69 | 70 | -------------------------------------------------------------------------------- /js/pool.js: -------------------------------------------------------------------------------- 1 | var env = require('./env.js') 2 | var ndarray = require("ndarray") 3 | var fill = require("ndarray-fill") 4 | 5 | function SpatialMaxPooling(kH, kW, dH, dW) { 6 | this.kH = kH 7 | this.kW = kW 8 | this.dH = dH 9 | this.dW = dW 10 | } 11 | 12 | SpatialMaxPooling.prototype.forward = function(input) { 13 | var nPlane = input.shape[0]; 14 | var iH = input.shape[1]; 15 | var iW = input.shape[2]; 16 | var kH = this.kH 17 | var kW = this.kW 18 | var dH = this.dH 19 | var dW = this.dW 20 | var oH = Math.floor((iH - kH) / dH + 1); 21 | var oW = Math.floor((iW - kW) / dW + 1); 22 | 23 | var output = ndarray(new Float32Array(nPlane * oH * oW), [nPlane, oH, oW]); 24 | 25 | var idata = input.data; 26 | var odata = output.data; 27 | 28 | for (k = 0; k < nPlane; k++) { 29 | /* loop over output */ 30 | var i, j; 31 | for(i = 0; i < oH; i++) { 32 | for(j = 0; j < oW; j++) { 33 | /* local pointers */ 34 | var ip = k*iW*iH + i*iW*dH + j*dW; 35 | var op = k*oW*oH + i*oW + j; 36 | 37 | /* compute local max: */ 38 | var maxval = -999999; 39 | var x,y; 40 | for(y = 0; y < kH; y++) { 41 | for(x = 0; x < kW; x++) { 42 | var val = idata[ip + y*iW + x]; 43 | if (val > maxval) { 44 | maxval = val; 45 | } 46 | } 47 | } 48 | /* set output to local max */ 49 | odata[op] = maxval; 50 | } 51 | } 52 | } 53 | return output; 54 | } 55 | 56 | env.SpatialMaxPooling = SpatialMaxPooling 57 | -------------------------------------------------------------------------------- /js/utils.js: -------------------------------------------------------------------------------- 1 | var ndarray = require("ndarray") 2 | var fill = require("ndarray-fill") 3 | var env = require("./env") 4 | 5 | var noise1d = function(n) { 6 | var arr = new ndarray(new Float32Array(n), [n]); 7 | fill(arr, function(k) { 8 | return (Math.random() * 2) - 1 9 | }) 10 | return arr; 11 | } 12 | 13 | var noise2d = function(n, m) { 14 | var arr = new ndarray(new Float32Array(n*m), [n, m]); 15 | fill(arr, function(k,j) { 16 | return (Math.random() * 2) - 1 17 | }) 18 | return arr; 19 | } 20 | 21 | var noise3d = function(n, m, k) { 22 | var arr = new ndarray(new Float32Array(n*m*k), [n, m, k]); 23 | fill(arr, function(h,i,j) { 24 | return (Math.random() * 2) - 1 25 | }) 26 | return arr; 27 | } 28 | 29 | 30 | var getPix = function(ip, k, i, j) { 31 | if ( i < 0 || i >= ip.shape[1] || j < 0 || j >= ip.shape[2]) { 32 | return 0; 33 | } else { 34 | return ip.get(k, i, j); 35 | } 36 | } 37 | 38 | var upscaleBilinear = function(inp, h, w) { 39 | var iH = inp.shape[1]; 40 | var iW = inp.shape[2]; 41 | var out = new ndarray(new Float32Array(3*h*w), [3, h, w]); 42 | for (var k=0; k < 3; k++) { 43 | for (var y = 0; y < h; y++) { 44 | for (var x = 0; x < w; x++) { 45 | var xx = x * iH / w; /* input width index (float) */ 46 | var yy = y * iW / h; /* input height index (float) */ 47 | var fx = xx|0; 48 | var fy = yy|0; 49 | if (fx === xx && fy === yy) { 50 | out.set(k, y, x, getPix(inp, k, fy, fx)) 51 | } else { 52 | var scale_xx = xx % 1; 53 | var scale_yy = yy % 1; 54 | var newVal = (1 - scale_yy) * ((1 - scale_xx) * getPix(inp, k, fy, fx) + scale_xx * getPix(inp, k, fy, fx+1)) + 55 | scale_yy * ((1 - scale_xx) * getPix(inp, k, fy+1, fx) + scale_xx * getPix(inp, k, fy+1, fx+1)); 56 | out.set(k, y, x, newVal); 57 | } 58 | } 59 | } 60 | } 61 | return out; 62 | } 63 | 64 | var minmaxnormalize = function(img, factor) { 65 | var f = factor || 256; 66 | // normalize output 67 | var min = 9999; 68 | var max = -9999; 69 | for (i=0; i < img.data.length; i++) { 70 | min = Math.min(min, img.data[i]) 71 | max = Math.max(max, img.data[i]) 72 | } 73 | max = max - min; 74 | for (i=0; i < img.data.length; i++) { 75 | img.data[i] += (-1 * min) 76 | img.data[i] = f * img.data[i] / max; 77 | } 78 | return img; 79 | } 80 | 81 | 82 | env.utils = {} 83 | env.utils.noise1d = noise1d 84 | env.utils.noise2d = noise2d 85 | env.utils.noise3d = noise3d 86 | env.utils.upscaleBilinear = upscaleBilinear 87 | env.utils.minMaxNormalize = minmaxnormalize 88 | -------------------------------------------------------------------------------- /nn.js: -------------------------------------------------------------------------------- 1 | static/js/nn.js -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nn", 3 | "version": "0.0.1", 4 | "description": "Fast neural networks for the browser in a Torch style API", 5 | "author": "Soumith Chintala ", 6 | "scripts": { 7 | "test": "mocha", 8 | "start": "node index.js", 9 | "compile": "browserify -r ./js/init.js:nn -r ndarray -r ndarray-fill -o static/js/nn.js" 10 | }, 11 | "main": "js/init.js", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/soumith/nnjs" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/soumith/nnjs/issues" 18 | }, 19 | "keywords": [ 20 | "neural networks", 21 | "torch", 22 | "deep learning" 23 | ], 24 | "dependencies": { 25 | "ndarray": "*", 26 | "ndarray-fill": "*", 27 | "msgpack-js": "*" 28 | }, 29 | "devDependencies": { 30 | "browserify": "*", 31 | "mocha": "*" 32 | }, 33 | "license": "BSD" 34 | } 35 | -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /static/js/benchmark.js: -------------------------------------------------------------------------------- 1 | nn = require('nn'); 2 | ndarray = require('ndarray'); 3 | 4 | function benchConvolution() { 5 | var sizes = 6 | [[3, 64, 5, 5, 32, 32], 7 | [4, 64, 5, 5, 32, 32], 8 | [64, 64, 5, 5, 32, 32], 9 | [64, 3, 5, 5, 32, 32], 10 | [64, 224, 5, 5, 32, 32], 11 | [128, 128, 7, 7, 28, 28], 12 | [256, 256, 7, 7, 14, 14]]; 13 | 14 | for (i=0; i < sizes.length; i++) { 15 | /////// Benchmark nn.js ////////////////////////////////// 16 | var c = sizes[i]; 17 | var weight = ndarray(new Float32Array(c[0]*c[1]*c[2]*c[3]), 18 | [c[1],c[2],c[3],c[0]]); 19 | var bias = ndarray(new Float32Array(c[1]), [c[1]]); 20 | var mod = new nn.SpatialConvolution(weight, bias, 0, 0); 21 | var inp = ndarray(new Float32Array(c[0]*c[4]*c[5]), 22 | [c[4],c[5],c[0]]); 23 | /* clock */ 24 | var start = performance.now(); 25 | var out = mod.forward(inp); 26 | var end = performance.now(); 27 | var timeNN = end - start; 28 | //////////// Benchmark convnet.js ////////////////////////// 29 | var layer_defs = []; 30 | layer_defs.push({type:'input', out_sx:c[4], out_sy:c[5], out_depth:c[0]}); 31 | layer_defs.push({type:'conv', sx:c[2], filters:c[1], 32 | stride:1, pad:0, activation:'relu'}); 33 | var net = new convnetjs.Net(); 34 | net.makeLayers(layer_defs); 35 | var x = new convnetjs.Vol(c[4], c[5], c[0]); 36 | var start = performance.now(); 37 | var out = net.forward(x) 38 | console.log(out) 39 | var end = performance.now(); 40 | var timeCNNJS = end - start; 41 | ///////////////////////////////////////////////////////// 42 | var logString = 'nn.SpatialConvolution(iChannels = ' + c[0] 43 | + ', oChannels = ' + c[1] + ', kH,kW = ' + c[2] + 'x' + c[3] 44 | + ', input = ' + c[0] + 'x' + c[4] + 'x' + c[5] + ').forward: ' 45 | + timeNN + ' ms convnetjs: ' + timeCNNJS + ' ms'; 46 | document.getElementById('main').innerHTML = 47 | document.getElementById('main').innerHTML + '
' + logString; 48 | console.log(logString); 49 | 50 | } 51 | } 52 | 53 | benchConvolution(); 54 | 55 | -------------------------------------------------------------------------------- /static/js/nn.js: -------------------------------------------------------------------------------- 1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);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= 0 && posH+ky < iH) { 158 | var iHPtr = iChan + ((posH + ky) * iW); 159 | var wHPtr = wOIChan + ky * kW; 160 | for(var kx = 0; kx < kW; kx++) { 161 | if(posW+kx >= 0 && posW+kx < iW) { 162 | sum += input.data[iHPtr + posW + kx] 163 | * weight.data[wHPtr + kx] 164 | } 165 | } 166 | } 167 | } 168 | /* Update output */ 169 | output.data[oPtr] = sum; 170 | posW++; 171 | } 172 | posH++; 173 | posW = -padW; 174 | } 175 | } 176 | } 177 | return output 178 | } 179 | 180 | env.SpatialConvolution = SpatialConvolution 181 | 182 | },{"./env.js":3,"ndarray":"ndarray","ndarray-fill":"ndarray-fill"}],3:[function(require,module,exports){ 183 | module.exports = { 184 | } 185 | 186 | },{}],4:[function(require,module,exports){ 187 | var env = require('./env.js') 188 | var ndarray = require("ndarray") 189 | var fill = require("ndarray-fill") 190 | 191 | /* weight is a 2D ndarray with dimensions 192 | [outSize, inpSize] 193 | 194 | bias is a 1D ndarray with dimensions 195 | [outSize] */ 196 | function Linear(weight, bias) { 197 | this.weight = weight; 198 | this.bias = bias; 199 | } 200 | 201 | Linear.prototype.forward = function(input) { 202 | var outSize = this.weight.shape[0]; 203 | var inSize = this.weight.shape[1]; 204 | var weight = this.weight; 205 | var bias = this.bias; 206 | var output = ndarray(new Float32Array(outSize), [outSize]); 207 | 208 | for (var i=0; i < outSize; i++) { 209 | var o = bias.get(i); 210 | for (var j=0; j < inSize; j++) { 211 | o += input.data[j] * weight.data[i * inSize + j]; 212 | } 213 | output.set(i, o); 214 | } 215 | return output 216 | } 217 | 218 | env.Linear = Linear 219 | 220 | },{"./env.js":3,"ndarray":"ndarray","ndarray-fill":"ndarray-fill"}],5:[function(require,module,exports){ 221 | var env = require('./env.js') 222 | var ndarray = require("ndarray") 223 | var assert = require('assert'); 224 | 225 | 226 | function loadFromObject(inp) { 227 | if (inp.type == 'Sequential') { 228 | var out = new env.Sequential() 229 | for (var i=0; i < inp.modules.length; i++) { 230 | out.add(loadFromObject(inp.modules[i])); 231 | } 232 | return out; 233 | } else if (inp.type == 'ParallelTable') { 234 | var out = new env.ParallelTable() 235 | for (var i=0; i < inp.modules.length; i++) { 236 | out.add(loadFromObject(inp.modules[i])); 237 | } 238 | return out; 239 | } else if (inp.type == 'JoinTable') { 240 | return new env.JoinTable(inp.dimension) 241 | } else if (inp.type == 'Identity') { 242 | return new env.Identity() 243 | } else if (inp.type == 'Linear') { 244 | var weight = new ndarray(inp.weight, 245 | [inp.outSize, inp.inSize]); 246 | var bias = new ndarray(inp.bias, [inp.outSize]) 247 | return new env.Linear(weight, bias) 248 | } else if (inp.type == 'ReLU') { 249 | return new env.ReLU() 250 | } else if (inp.type == 'View') { 251 | return new env.View(inp.dims) 252 | } else if (inp.type == 'SpatialConvolution') { 253 | var weight = new ndarray(inp.weight, 254 | [inp.nOutputPlane, inp.nInputPlane, 255 | inp.kH, inp.kW]); 256 | var bias = new ndarray(inp.bias, [inp.nOutputPlane]) 257 | return new env.SpatialConvolution(weight, bias, 258 | inp.padH, inp.padW) 259 | } else { 260 | throw('Error: Unknown module: ' + inp.type); 261 | } 262 | } 263 | 264 | function loadFromJSON(inp) { 265 | var input = JSON.parse(inp); 266 | return loadFromObject(input); 267 | } 268 | 269 | var msgpack = require('msgpack-js'); 270 | function loadFromMsgPack(input) { 271 | var output = msgpack.decode(input); 272 | return loadFromObject(output); 273 | } 274 | 275 | // var pako = require('pako'); 276 | // function loadFromGZipMsgPack(input) { 277 | // var output = pako.deflate(input); 278 | // return loadFromMsgPack(output); 279 | // } 280 | 281 | // function loadFromGZipJSON(input) { 282 | // var output = pako.deflate(input); 283 | // return loadFromJSON(output); 284 | // } 285 | 286 | env.loadFromJSON = loadFromJSON 287 | env.loadFromMsgPack = loadFromMsgPack 288 | 289 | // env.loadFromGZipMsgPack = loadFromGZipMsgPack 290 | // env.loadFromGZipJSON = loadFromGZipJSON 291 | 292 | },{"./env.js":3,"assert":30,"msgpack-js":9,"ndarray":"ndarray"}],6:[function(require,module,exports){ 293 | var env = require('./env.js') 294 | var ndarray = require("ndarray") 295 | 296 | function ReLU() {} 297 | 298 | /* in-place ReLU */ 299 | ReLU.prototype.forward = function(input) { 300 | var d = input.data; 301 | for (var i=0; i < d.length; i++) { 302 | if (d[i] < 0) { 303 | d[i] = 0 304 | } 305 | } 306 | return input 307 | } 308 | 309 | env.ReLU = ReLU 310 | 311 | //////////////////////////////////////////////////////// 312 | 313 | function View(shape) { 314 | this.shape = shape; 315 | } 316 | 317 | View.prototype.forward = function(input) { 318 | var output = new ndarray(input.data, this.shape) 319 | return output 320 | } 321 | 322 | env.View = View 323 | 324 | //////////////////////////////////////////////////////// 325 | 326 | function Identity() {} 327 | 328 | Identity.prototype.forward = function(input) { 329 | return input 330 | } 331 | 332 | env.Identity = Identity 333 | ///////////////////////////////////////////////////////// 334 | 335 | function DHWtoHWD() { 336 | } 337 | 338 | DHWtoHWD.prototype.forward = function(input) { 339 | if (input.shape.length != 3) { 340 | throw('Not supported dims') 341 | } 342 | var outShape = []; 343 | var footprint = 1; 344 | outShape[0] = input.shape[1]; 345 | outShape[1] = input.shape[2]; 346 | outShape[2] = input.shape[0]; 347 | for (i=0; i < input.shape.length; i++) { 348 | footprint = footprint * input.shape[i]; 349 | } 350 | var output = new ndarray(new Float32Array(footprint), outShape); 351 | for (i=0; i < outShape[0]; i++) { 352 | for (j=0; j < outShape[1]; j++) { 353 | for (k=0; k < outShape[2]; k++) { 354 | output.set(i, j, k, input.get(k, i, j)) 355 | } 356 | } 357 | } 358 | return output 359 | } 360 | env.DHWtoHWD = DHWtoHWD 361 | 362 | 363 | },{"./env.js":3,"ndarray":"ndarray"}],7:[function(require,module,exports){ 364 | var env = require('./env.js') 365 | var ndarray = require("ndarray") 366 | var fill = require("ndarray-fill") 367 | 368 | function SpatialMaxPooling(kH, kW, dH, dW) { 369 | this.kH = kH 370 | this.kW = kW 371 | this.dH = dH 372 | this.dW = dW 373 | } 374 | 375 | SpatialMaxPooling.prototype.forward = function(input) { 376 | var nPlane = input.shape[0]; 377 | var iH = input.shape[1]; 378 | var iW = input.shape[2]; 379 | var kH = this.kH 380 | var kW = this.kW 381 | var dH = this.dH 382 | var dW = this.dW 383 | var oH = Math.floor((iH - kH) / dH + 1); 384 | var oW = Math.floor((iW - kW) / dW + 1); 385 | 386 | var output = ndarray(new Float32Array(nPlane * oH * oW), [nPlane, oH, oW]); 387 | 388 | var idata = input.data; 389 | var odata = output.data; 390 | 391 | for (k = 0; k < nPlane; k++) { 392 | /* loop over output */ 393 | var i, j; 394 | for(i = 0; i < oH; i++) { 395 | for(j = 0; j < oW; j++) { 396 | /* local pointers */ 397 | var ip = k*iW*iH + i*iW*dH + j*dW; 398 | var op = k*oW*oH + i*oW + j; 399 | 400 | /* compute local max: */ 401 | var maxval = -999999; 402 | var x,y; 403 | for(y = 0; y < kH; y++) { 404 | for(x = 0; x < kW; x++) { 405 | var val = idata[ip + y*iW + x]; 406 | if (val > maxval) { 407 | maxval = val; 408 | } 409 | } 410 | } 411 | /* set output to local max */ 412 | odata[op] = maxval; 413 | } 414 | } 415 | } 416 | return output; 417 | } 418 | 419 | env.SpatialMaxPooling = SpatialMaxPooling 420 | 421 | },{"./env.js":3,"ndarray":"ndarray","ndarray-fill":"ndarray-fill"}],8:[function(require,module,exports){ 422 | var ndarray = require("ndarray") 423 | var fill = require("ndarray-fill") 424 | var env = require("./env") 425 | 426 | var noise1d = function(n) { 427 | var arr = new ndarray(new Float32Array(n), [n]); 428 | fill(arr, function(k) { 429 | return (Math.random() * 2) - 1 430 | }) 431 | return arr; 432 | } 433 | 434 | var noise2d = function(n, m) { 435 | var arr = new ndarray(new Float32Array(n*m), [n, m]); 436 | fill(arr, function(k,j) { 437 | return (Math.random() * 2) - 1 438 | }) 439 | return arr; 440 | } 441 | 442 | var noise3d = function(n, m, k) { 443 | var arr = new ndarray(new Float32Array(n*m*k), [n, m, k]); 444 | fill(arr, function(h,i,j) { 445 | return (Math.random() * 2) - 1 446 | }) 447 | return arr; 448 | } 449 | 450 | 451 | var getPix = function(ip, k, i, j) { 452 | if ( i < 0 || i >= ip.shape[1] || j < 0 || j >= ip.shape[2]) { 453 | return 0; 454 | } else { 455 | return ip.get(k, i, j); 456 | } 457 | } 458 | 459 | var upscaleBilinear = function(inp, h, w) { 460 | var iH = inp.shape[1]; 461 | var iW = inp.shape[2]; 462 | var out = new ndarray(new Float32Array(3*h*w), [3, h, w]); 463 | for (var k=0; k < 3; k++) { 464 | for (var y = 0; y < h; y++) { 465 | for (var x = 0; x < w; x++) { 466 | var xx = x * iH / w; /* input width index (float) */ 467 | var yy = y * iW / h; /* input height index (float) */ 468 | var fx = xx|0; 469 | var fy = yy|0; 470 | if (fx === xx && fy === yy) { 471 | out.set(k, y, x, getPix(inp, k, fy, fx)) 472 | } else { 473 | var scale_xx = xx % 1; 474 | var scale_yy = yy % 1; 475 | var newVal = (1 - scale_yy) * ((1 - scale_xx) * getPix(inp, k, fy, fx) + scale_xx * getPix(inp, k, fy, fx+1)) + 476 | scale_yy * ((1 - scale_xx) * getPix(inp, k, fy+1, fx) + scale_xx * getPix(inp, k, fy+1, fx+1)); 477 | out.set(k, y, x, newVal); 478 | } 479 | } 480 | } 481 | } 482 | return out; 483 | } 484 | 485 | var minmaxnormalize = function(img, factor) { 486 | var f = factor || 256; 487 | // normalize output 488 | var min = 9999; 489 | var max = -9999; 490 | for (i=0; i < img.data.length; i++) { 491 | min = Math.min(min, img.data[i]) 492 | max = Math.max(max, img.data[i]) 493 | } 494 | max = max - min; 495 | for (i=0; i < img.data.length; i++) { 496 | img.data[i] += (-1 * min) 497 | img.data[i] = f * img.data[i] / max; 498 | } 499 | return img; 500 | } 501 | 502 | 503 | env.utils = {} 504 | env.utils.noise1d = noise1d 505 | env.utils.noise2d = noise2d 506 | env.utils.noise3d = noise3d 507 | env.utils.upscaleBilinear = upscaleBilinear 508 | env.utils.minMaxNormalize = minmaxnormalize 509 | 510 | },{"./env":3,"ndarray":"ndarray","ndarray-fill":"ndarray-fill"}],9:[function(require,module,exports){ 511 | "use strict"; 512 | 513 | var bops = require('bops'); 514 | 515 | exports.encode = function (value) { 516 | var toJSONed = [] 517 | var size = sizeof(value) 518 | if(size == 0) 519 | return undefined 520 | var buffer = bops.create(size); 521 | encode(value, buffer, 0); 522 | return buffer; 523 | }; 524 | 525 | exports.decode = decode; 526 | 527 | // http://wiki.msgpack.org/display/MSGPACK/Format+specification 528 | // I've extended the protocol to have two new types that were previously reserved. 529 | // buffer 16 11011000 0xd8 530 | // buffer 32 11011001 0xd9 531 | // These work just like raw16 and raw32 except they are node buffers instead of strings. 532 | // 533 | // Also I've added a type for `undefined` 534 | // undefined 11000100 0xc4 535 | 536 | function Decoder(buffer, offset) { 537 | this.offset = offset || 0; 538 | this.buffer = buffer; 539 | } 540 | Decoder.prototype.map = function (length) { 541 | var value = {}; 542 | for (var i = 0; i < length; i++) { 543 | var key = this.parse(); 544 | value[key] = this.parse(); 545 | } 546 | return value; 547 | }; 548 | Decoder.prototype.buf = function (length) { 549 | var value = bops.subarray(this.buffer, this.offset, this.offset + length); 550 | this.offset += length; 551 | return value; 552 | }; 553 | Decoder.prototype.raw = function (length) { 554 | var value = bops.to(bops.subarray(this.buffer, this.offset, this.offset + length)); 555 | this.offset += length; 556 | return value; 557 | }; 558 | Decoder.prototype.array = function (length) { 559 | var value = new Array(length); 560 | for (var i = 0; i < length; i++) { 561 | value[i] = this.parse(); 562 | } 563 | return value; 564 | }; 565 | Decoder.prototype.parse = function () { 566 | var type = this.buffer[this.offset]; 567 | var value, length; 568 | // FixRaw 569 | if ((type & 0xe0) === 0xa0) { 570 | length = type & 0x1f; 571 | this.offset++; 572 | return this.raw(length); 573 | } 574 | // FixMap 575 | if ((type & 0xf0) === 0x80) { 576 | length = type & 0x0f; 577 | this.offset++; 578 | return this.map(length); 579 | } 580 | // FixArray 581 | if ((type & 0xf0) === 0x90) { 582 | length = type & 0x0f; 583 | this.offset++; 584 | return this.array(length); 585 | } 586 | // Positive FixNum 587 | if ((type & 0x80) === 0x00) { 588 | this.offset++; 589 | return type; 590 | } 591 | // Negative Fixnum 592 | if ((type & 0xe0) === 0xe0) { 593 | value = bops.readInt8(this.buffer, this.offset); 594 | this.offset++; 595 | return value; 596 | } 597 | switch (type) { 598 | // raw 16 599 | case 0xda: 600 | length = bops.readUInt16BE(this.buffer, this.offset + 1); 601 | this.offset += 3; 602 | return this.raw(length); 603 | // raw 32 604 | case 0xdb: 605 | length = bops.readUInt32BE(this.buffer, this.offset + 1); 606 | this.offset += 5; 607 | return this.raw(length); 608 | // nil 609 | case 0xc0: 610 | this.offset++; 611 | return null; 612 | // false 613 | case 0xc2: 614 | this.offset++; 615 | return false; 616 | // true 617 | case 0xc3: 618 | this.offset++; 619 | return true; 620 | // undefined 621 | case 0xc4: 622 | this.offset++; 623 | return undefined; 624 | // uint8 625 | case 0xcc: 626 | value = this.buffer[this.offset + 1]; 627 | this.offset += 2; 628 | return value; 629 | // uint 16 630 | case 0xcd: 631 | value = bops.readUInt16BE(this.buffer, this.offset + 1); 632 | this.offset += 3; 633 | return value; 634 | // uint 32 635 | case 0xce: 636 | value = bops.readUInt32BE(this.buffer, this.offset + 1); 637 | this.offset += 5; 638 | return value; 639 | // uint64 640 | case 0xcf: 641 | value = bops.readUInt64BE(this.buffer, this.offset + 1); 642 | this.offset += 9; 643 | return value; 644 | // int 8 645 | case 0xd0: 646 | value = bops.readInt8(this.buffer, this.offset + 1); 647 | this.offset += 2; 648 | return value; 649 | // int 16 650 | case 0xd1: 651 | value = bops.readInt16BE(this.buffer, this.offset + 1); 652 | this.offset += 3; 653 | return value; 654 | // int 32 655 | case 0xd2: 656 | value = bops.readInt32BE(this.buffer, this.offset + 1); 657 | this.offset += 5; 658 | return value; 659 | // int 64 660 | case 0xd3: 661 | value = bops.readInt64BE(this.buffer, this.offset + 1); 662 | this.offset += 9; 663 | return value; 664 | // map 16 665 | case 0xde: 666 | length = bops.readUInt16BE(this.buffer, this.offset + 1); 667 | this.offset += 3; 668 | return this.map(length); 669 | // map 32 670 | case 0xdf: 671 | length = bops.readUInt32BE(this.buffer, this.offset + 1); 672 | this.offset += 5; 673 | return this.map(length); 674 | // array 16 675 | case 0xdc: 676 | length = bops.readUInt16BE(this.buffer, this.offset + 1); 677 | this.offset += 3; 678 | return this.array(length); 679 | // array 32 680 | case 0xdd: 681 | length = bops.readUInt32BE(this.buffer, this.offset + 1); 682 | this.offset += 5; 683 | return this.array(length); 684 | // buffer 16 685 | case 0xd8: 686 | length = bops.readUInt16BE(this.buffer, this.offset + 1); 687 | this.offset += 3; 688 | return this.buf(length); 689 | // buffer 32 690 | case 0xd9: 691 | length = bops.readUInt32BE(this.buffer, this.offset + 1); 692 | this.offset += 5; 693 | return this.buf(length); 694 | // float 695 | case 0xca: 696 | value = bops.readFloatBE(this.buffer, this.offset + 1); 697 | this.offset += 5; 698 | return value; 699 | // double 700 | case 0xcb: 701 | value = bops.readDoubleBE(this.buffer, this.offset + 1); 702 | this.offset += 9; 703 | return value; 704 | } 705 | throw new Error("Unknown type 0x" + type.toString(16)); 706 | }; 707 | function decode(buffer) { 708 | var decoder = new Decoder(buffer); 709 | var value = decoder.parse(); 710 | if (decoder.offset !== buffer.length) throw new Error((buffer.length - decoder.offset) + " trailing bytes"); 711 | return value; 712 | } 713 | 714 | function encodeableKeys (value) { 715 | return Object.keys(value).filter(function (e) { 716 | return 'function' !== typeof value[e] || !!value[e].toJSON 717 | }) 718 | } 719 | 720 | function encode(value, buffer, offset) { 721 | var type = typeof value; 722 | var length, size; 723 | 724 | // Strings Bytes 725 | if (type === "string") { 726 | value = bops.from(value); 727 | length = value.length; 728 | // fix raw 729 | if (length < 0x20) { 730 | buffer[offset] = length | 0xa0; 731 | bops.copy(value, buffer, offset + 1); 732 | return 1 + length; 733 | } 734 | // raw 16 735 | if (length < 0x10000) { 736 | buffer[offset] = 0xda; 737 | bops.writeUInt16BE(buffer, length, offset + 1); 738 | bops.copy(value, buffer, offset + 3); 739 | return 3 + length; 740 | } 741 | // raw 32 742 | if (length < 0x100000000) { 743 | buffer[offset] = 0xdb; 744 | bops.writeUInt32BE(buffer, length, offset + 1); 745 | bops.copy(value, buffer, offset + 5); 746 | return 5 + length; 747 | } 748 | } 749 | 750 | if (bops.is(value)) { 751 | length = value.length; 752 | // buffer 16 753 | if (length < 0x10000) { 754 | buffer[offset] = 0xd8; 755 | bops.writeUInt16BE(buffer, length, offset + 1); 756 | bops.copy(value, buffer, offset + 3); 757 | return 3 + length; 758 | } 759 | // buffer 32 760 | if (length < 0x100000000) { 761 | buffer[offset] = 0xd9; 762 | bops.writeUInt32BE(buffer, length, offset + 1); 763 | bops.copy(value, buffer, offset + 5); 764 | return 5 + length; 765 | } 766 | } 767 | 768 | if (type === "number") { 769 | // Floating Point 770 | if ((value << 0) !== value) { 771 | buffer[offset] = 0xcb; 772 | bops.writeDoubleBE(buffer, value, offset + 1); 773 | return 9; 774 | } 775 | 776 | // Integers 777 | if (value >=0) { 778 | // positive fixnum 779 | if (value < 0x80) { 780 | buffer[offset] = value; 781 | return 1; 782 | } 783 | // uint 8 784 | if (value < 0x100) { 785 | buffer[offset] = 0xcc; 786 | buffer[offset + 1] = value; 787 | return 2; 788 | } 789 | // uint 16 790 | if (value < 0x10000) { 791 | buffer[offset] = 0xcd; 792 | bops.writeUInt16BE(buffer, value, offset + 1); 793 | return 3; 794 | } 795 | // uint 32 796 | if (value < 0x100000000) { 797 | buffer[offset] = 0xce; 798 | bops.writeUInt32BE(buffer, value, offset + 1); 799 | return 5; 800 | } 801 | // uint 64 802 | if (value < 0x10000000000000000) { 803 | buffer[offset] = 0xcf; 804 | bops.writeUInt64BE(buffer, value, offset + 1); 805 | return 9; 806 | } 807 | throw new Error("Number too big 0x" + value.toString(16)); 808 | } 809 | // negative fixnum 810 | if (value >= -0x20) { 811 | bops.writeInt8(buffer, value, offset); 812 | return 1; 813 | } 814 | // int 8 815 | if (value >= -0x80) { 816 | buffer[offset] = 0xd0; 817 | bops.writeInt8(buffer, value, offset + 1); 818 | return 2; 819 | } 820 | // int 16 821 | if (value >= -0x8000) { 822 | buffer[offset] = 0xd1; 823 | bops.writeInt16BE(buffer, value, offset + 1); 824 | return 3; 825 | } 826 | // int 32 827 | if (value >= -0x80000000) { 828 | buffer[offset] = 0xd2; 829 | bops.writeInt32BE(buffer, value, offset + 1); 830 | return 5; 831 | } 832 | // int 64 833 | if (value >= -0x8000000000000000) { 834 | buffer[offset] = 0xd3; 835 | bops.writeInt64BE(buffer, value, offset + 1); 836 | return 9; 837 | } 838 | throw new Error("Number too small -0x" + value.toString(16).substr(1)); 839 | } 840 | 841 | // undefined 842 | if (type === "undefined") { 843 | buffer[offset] = 0xc4; 844 | return 1; 845 | } 846 | 847 | // null 848 | if (value === null) { 849 | buffer[offset] = 0xc0; 850 | return 1; 851 | } 852 | 853 | // Boolean 854 | if (type === "boolean") { 855 | buffer[offset] = value ? 0xc3 : 0xc2; 856 | return 1; 857 | } 858 | 859 | if('function' === typeof value.toJSON) 860 | return encode(value.toJSON(), buffer, offset) 861 | 862 | // Container Types 863 | if (type === "object") { 864 | 865 | size = 0; 866 | var isArray = Array.isArray(value); 867 | 868 | if (isArray) { 869 | length = value.length; 870 | } 871 | else { 872 | var keys = encodeableKeys(value) 873 | length = keys.length; 874 | } 875 | 876 | if (length < 0x10) { 877 | buffer[offset] = length | (isArray ? 0x90 : 0x80); 878 | size = 1; 879 | } 880 | else if (length < 0x10000) { 881 | buffer[offset] = isArray ? 0xdc : 0xde; 882 | bops.writeUInt16BE(buffer, length, offset + 1); 883 | size = 3; 884 | } 885 | else if (length < 0x100000000) { 886 | buffer[offset] = isArray ? 0xdd : 0xdf; 887 | bops.writeUInt32BE(buffer, length, offset + 1); 888 | size = 5; 889 | } 890 | 891 | if (isArray) { 892 | for (var i = 0; i < length; i++) { 893 | size += encode(value[i], buffer, offset + size); 894 | } 895 | } 896 | else { 897 | for (var i = 0; i < length; i++) { 898 | var key = keys[i]; 899 | size += encode(key, buffer, offset + size); 900 | size += encode(value[key], buffer, offset + size); 901 | } 902 | } 903 | 904 | return size; 905 | } 906 | if(type === "function") 907 | return undefined 908 | throw new Error("Unknown type " + type); 909 | } 910 | 911 | function sizeof(value) { 912 | var type = typeof value; 913 | var length, size; 914 | 915 | // Raw Bytes 916 | if (type === "string") { 917 | // TODO: this creates a throw-away buffer which is probably expensive on browsers. 918 | length = bops.from(value).length; 919 | if (length < 0x20) { 920 | return 1 + length; 921 | } 922 | if (length < 0x10000) { 923 | return 3 + length; 924 | } 925 | if (length < 0x100000000) { 926 | return 5 + length; 927 | } 928 | } 929 | 930 | if (bops.is(value)) { 931 | length = value.length; 932 | if (length < 0x10000) { 933 | return 3 + length; 934 | } 935 | if (length < 0x100000000) { 936 | return 5 + length; 937 | } 938 | } 939 | 940 | if (type === "number") { 941 | // Floating Point 942 | // double 943 | if (value << 0 !== value) return 9; 944 | 945 | // Integers 946 | if (value >=0) { 947 | // positive fixnum 948 | if (value < 0x80) return 1; 949 | // uint 8 950 | if (value < 0x100) return 2; 951 | // uint 16 952 | if (value < 0x10000) return 3; 953 | // uint 32 954 | if (value < 0x100000000) return 5; 955 | // uint 64 956 | if (value < 0x10000000000000000) return 9; 957 | throw new Error("Number too big 0x" + value.toString(16)); 958 | } 959 | // negative fixnum 960 | if (value >= -0x20) return 1; 961 | // int 8 962 | if (value >= -0x80) return 2; 963 | // int 16 964 | if (value >= -0x8000) return 3; 965 | // int 32 966 | if (value >= -0x80000000) return 5; 967 | // int 64 968 | if (value >= -0x8000000000000000) return 9; 969 | throw new Error("Number too small -0x" + value.toString(16).substr(1)); 970 | } 971 | 972 | // Boolean, null, undefined 973 | if (type === "boolean" || type === "undefined" || value === null) return 1; 974 | 975 | if('function' === typeof value.toJSON) 976 | return sizeof(value.toJSON()) 977 | 978 | // Container Types 979 | if (type === "object") { 980 | if('function' === typeof value.toJSON) 981 | value = value.toJSON() 982 | 983 | size = 0; 984 | if (Array.isArray(value)) { 985 | length = value.length; 986 | for (var i = 0; i < length; i++) { 987 | size += sizeof(value[i]); 988 | } 989 | } 990 | else { 991 | var keys = encodeableKeys(value) 992 | length = keys.length; 993 | for (var i = 0; i < length; i++) { 994 | var key = keys[i]; 995 | size += sizeof(key) + sizeof(value[key]); 996 | } 997 | } 998 | if (length < 0x10) { 999 | return 1 + size; 1000 | } 1001 | if (length < 0x10000) { 1002 | return 3 + size; 1003 | } 1004 | if (length < 0x100000000) { 1005 | return 5 + size; 1006 | } 1007 | throw new Error("Array or object too long 0x" + length.toString(16)); 1008 | } 1009 | if(type === "function") 1010 | return 0 1011 | throw new Error("Unknown type " + type); 1012 | } 1013 | 1014 | 1015 | 1016 | },{"bops":10}],10:[function(require,module,exports){ 1017 | var proto = {} 1018 | module.exports = proto 1019 | 1020 | proto.from = require('./from.js') 1021 | proto.to = require('./to.js') 1022 | proto.is = require('./is.js') 1023 | proto.subarray = require('./subarray.js') 1024 | proto.join = require('./join.js') 1025 | proto.copy = require('./copy.js') 1026 | proto.create = require('./create.js') 1027 | 1028 | mix(require('./read.js'), proto) 1029 | mix(require('./write.js'), proto) 1030 | 1031 | function mix(from, into) { 1032 | for(var key in from) { 1033 | into[key] = from[key] 1034 | } 1035 | } 1036 | 1037 | },{"./copy.js":13,"./create.js":14,"./from.js":15,"./is.js":16,"./join.js":17,"./read.js":19,"./subarray.js":20,"./to.js":21,"./write.js":22}],11:[function(require,module,exports){ 1038 | (function (exports) { 1039 | 'use strict'; 1040 | 1041 | var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 1042 | 1043 | function b64ToByteArray(b64) { 1044 | var i, j, l, tmp, placeHolders, arr; 1045 | 1046 | if (b64.length % 4 > 0) { 1047 | throw 'Invalid string. Length must be a multiple of 4'; 1048 | } 1049 | 1050 | // the number of equal signs (place holders) 1051 | // if there are two placeholders, than the two characters before it 1052 | // represent one byte 1053 | // if there is only one, then the three characters before it represent 2 bytes 1054 | // this is just a cheap hack to not do indexOf twice 1055 | placeHolders = b64.indexOf('='); 1056 | placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0; 1057 | 1058 | // base64 is 4/3 + up to two characters of the original data 1059 | arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders); 1060 | 1061 | // if there are placeholders, only get up to the last complete 4 chars 1062 | l = placeHolders > 0 ? b64.length - 4 : b64.length; 1063 | 1064 | for (i = 0, j = 0; i < l; i += 4, j += 3) { 1065 | tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]); 1066 | arr.push((tmp & 0xFF0000) >> 16); 1067 | arr.push((tmp & 0xFF00) >> 8); 1068 | arr.push(tmp & 0xFF); 1069 | } 1070 | 1071 | if (placeHolders === 2) { 1072 | tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4); 1073 | arr.push(tmp & 0xFF); 1074 | } else if (placeHolders === 1) { 1075 | tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2); 1076 | arr.push((tmp >> 8) & 0xFF); 1077 | arr.push(tmp & 0xFF); 1078 | } 1079 | 1080 | return arr; 1081 | } 1082 | 1083 | function uint8ToBase64(uint8) { 1084 | var i, 1085 | extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes 1086 | output = "", 1087 | temp, length; 1088 | 1089 | function tripletToBase64 (num) { 1090 | return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; 1091 | }; 1092 | 1093 | // go through the array every three bytes, we'll deal with trailing stuff later 1094 | for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { 1095 | temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]); 1096 | output += tripletToBase64(temp); 1097 | } 1098 | 1099 | // pad the end with zeros, but make sure to not forget the extra bytes 1100 | switch (extraBytes) { 1101 | case 1: 1102 | temp = uint8[uint8.length - 1]; 1103 | output += lookup[temp >> 2]; 1104 | output += lookup[(temp << 4) & 0x3F]; 1105 | output += '=='; 1106 | break; 1107 | case 2: 1108 | temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]); 1109 | output += lookup[temp >> 10]; 1110 | output += lookup[(temp >> 4) & 0x3F]; 1111 | output += lookup[(temp << 2) & 0x3F]; 1112 | output += '='; 1113 | break; 1114 | } 1115 | 1116 | return output; 1117 | } 1118 | 1119 | module.exports.toByteArray = b64ToByteArray; 1120 | module.exports.fromByteArray = uint8ToBase64; 1121 | }()); 1122 | 1123 | },{}],12:[function(require,module,exports){ 1124 | module.exports = to_utf8 1125 | 1126 | var out = [] 1127 | , col = [] 1128 | , fcc = String.fromCharCode 1129 | , mask = [0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01] 1130 | , unmask = [ 1131 | 0x00 1132 | , 0x01 1133 | , 0x02 | 0x01 1134 | , 0x04 | 0x02 | 0x01 1135 | , 0x08 | 0x04 | 0x02 | 0x01 1136 | , 0x10 | 0x08 | 0x04 | 0x02 | 0x01 1137 | , 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 1138 | , 0x40 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 1139 | ] 1140 | 1141 | function to_utf8(bytes, start, end) { 1142 | start = start === undefined ? 0 : start 1143 | end = end === undefined ? bytes.length : end 1144 | 1145 | var idx = 0 1146 | , hi = 0x80 1147 | , collecting = 0 1148 | , pos 1149 | , by 1150 | 1151 | col.length = 1152 | out.length = 0 1153 | 1154 | while(idx < bytes.length) { 1155 | by = bytes[idx] 1156 | if(!collecting && by & hi) { 1157 | pos = find_pad_position(by) 1158 | collecting += pos 1159 | if(pos < 8) { 1160 | col[col.length] = by & unmask[6 - pos] 1161 | } 1162 | } else if(collecting) { 1163 | col[col.length] = by & unmask[6] 1164 | --collecting 1165 | if(!collecting && col.length) { 1166 | out[out.length] = fcc(reduced(col, pos)) 1167 | col.length = 0 1168 | } 1169 | } else { 1170 | out[out.length] = fcc(by) 1171 | } 1172 | ++idx 1173 | } 1174 | if(col.length && !collecting) { 1175 | out[out.length] = fcc(reduced(col, pos)) 1176 | col.length = 0 1177 | } 1178 | return out.join('') 1179 | } 1180 | 1181 | function find_pad_position(byt) { 1182 | for(var i = 0; i < 7; ++i) { 1183 | if(!(byt & mask[i])) { 1184 | break 1185 | } 1186 | } 1187 | return i 1188 | } 1189 | 1190 | function reduced(list) { 1191 | var out = 0 1192 | for(var i = 0, len = list.length; i < len; ++i) { 1193 | out |= list[i] << ((len - i - 1) * 6) 1194 | } 1195 | return out 1196 | } 1197 | 1198 | },{}],13:[function(require,module,exports){ 1199 | module.exports = copy 1200 | 1201 | var slice = [].slice 1202 | 1203 | function copy(source, target, target_start, source_start, source_end) { 1204 | target_start = arguments.length < 3 ? 0 : target_start 1205 | source_start = arguments.length < 4 ? 0 : source_start 1206 | source_end = arguments.length < 5 ? source.length : source_end 1207 | 1208 | if(source_end === source_start) { 1209 | return 1210 | } 1211 | 1212 | if(target.length === 0 || source.length === 0) { 1213 | return 1214 | } 1215 | 1216 | if(source_end > source.length) { 1217 | source_end = source.length 1218 | } 1219 | 1220 | if(target.length - target_start < source_end - source_start) { 1221 | source_end = target.length - target_start + source_start 1222 | } 1223 | 1224 | if(source.buffer !== target.buffer) { 1225 | return fast_copy(source, target, target_start, source_start, source_end) 1226 | } 1227 | return slow_copy(source, target, target_start, source_start, source_end) 1228 | } 1229 | 1230 | function fast_copy(source, target, target_start, source_start, source_end) { 1231 | var len = (source_end - source_start) + target_start 1232 | 1233 | for(var i = target_start, j = source_start; 1234 | i < len; 1235 | ++i, 1236 | ++j) { 1237 | target[i] = source[j] 1238 | } 1239 | } 1240 | 1241 | function slow_copy(from, to, j, i, jend) { 1242 | // the buffers could overlap. 1243 | var iend = jend + i 1244 | , tmp = new Uint8Array(slice.call(from, i, iend)) 1245 | , x = 0 1246 | 1247 | for(; i < iend; ++i, ++x) { 1248 | to[j++] = tmp[x] 1249 | } 1250 | } 1251 | 1252 | },{}],14:[function(require,module,exports){ 1253 | module.exports = function(size) { 1254 | return new Uint8Array(size) 1255 | } 1256 | 1257 | },{}],15:[function(require,module,exports){ 1258 | module.exports = from 1259 | 1260 | var base64 = require('base64-js') 1261 | 1262 | var decoders = { 1263 | hex: from_hex 1264 | , utf8: from_utf 1265 | , base64: from_base64 1266 | } 1267 | 1268 | function from(source, encoding) { 1269 | if(Array.isArray(source)) { 1270 | return new Uint8Array(source) 1271 | } 1272 | 1273 | return decoders[encoding || 'utf8'](source) 1274 | } 1275 | 1276 | function from_hex(str) { 1277 | var size = str.length / 2 1278 | , buf = new Uint8Array(size) 1279 | , character = '' 1280 | 1281 | for(var i = 0, len = str.length; i < len; ++i) { 1282 | character += str.charAt(i) 1283 | 1284 | if(i > 0 && (i % 2) === 1) { 1285 | buf[i>>>1] = parseInt(character, 16) 1286 | character = '' 1287 | } 1288 | } 1289 | 1290 | return buf 1291 | } 1292 | 1293 | function from_utf(str) { 1294 | var bytes = [] 1295 | , tmp 1296 | , ch 1297 | 1298 | for(var i = 0, len = str.length; i < len; ++i) { 1299 | ch = str.charCodeAt(i) 1300 | if(ch & 0x80) { 1301 | tmp = encodeURIComponent(str.charAt(i)).substr(1).split('%') 1302 | for(var j = 0, jlen = tmp.length; j < jlen; ++j) { 1303 | bytes[bytes.length] = parseInt(tmp[j], 16) 1304 | } 1305 | } else { 1306 | bytes[bytes.length] = ch 1307 | } 1308 | } 1309 | 1310 | return new Uint8Array(bytes) 1311 | } 1312 | 1313 | function from_base64(str) { 1314 | return new Uint8Array(base64.toByteArray(str)) 1315 | } 1316 | 1317 | },{"base64-js":11}],16:[function(require,module,exports){ 1318 | 1319 | module.exports = function(buffer) { 1320 | return buffer instanceof Uint8Array; 1321 | } 1322 | 1323 | },{}],17:[function(require,module,exports){ 1324 | module.exports = join 1325 | 1326 | function join(targets, hint) { 1327 | if(!targets.length) { 1328 | return new Uint8Array(0) 1329 | } 1330 | 1331 | var len = hint !== undefined ? hint : get_length(targets) 1332 | , out = new Uint8Array(len) 1333 | , cur = targets[0] 1334 | , curlen = cur.length 1335 | , curidx = 0 1336 | , curoff = 0 1337 | , i = 0 1338 | 1339 | while(i < len) { 1340 | if(curoff === curlen) { 1341 | curoff = 0 1342 | ++curidx 1343 | cur = targets[curidx] 1344 | curlen = cur && cur.length 1345 | continue 1346 | } 1347 | out[i++] = cur[curoff++] 1348 | } 1349 | 1350 | return out 1351 | } 1352 | 1353 | function get_length(targets) { 1354 | var size = 0 1355 | for(var i = 0, len = targets.length; i < len; ++i) { 1356 | size += targets[i].byteLength 1357 | } 1358 | return size 1359 | } 1360 | 1361 | },{}],18:[function(require,module,exports){ 1362 | var proto 1363 | , map 1364 | 1365 | module.exports = proto = {} 1366 | 1367 | map = typeof WeakMap === 'undefined' ? null : new WeakMap 1368 | 1369 | proto.get = !map ? no_weakmap_get : get 1370 | 1371 | function no_weakmap_get(target) { 1372 | return new DataView(target.buffer, 0) 1373 | } 1374 | 1375 | function get(target) { 1376 | var out = map.get(target.buffer) 1377 | if(!out) { 1378 | map.set(target.buffer, out = new DataView(target.buffer, 0)) 1379 | } 1380 | return out 1381 | } 1382 | 1383 | },{}],19:[function(require,module,exports){ 1384 | module.exports = { 1385 | readUInt8: read_uint8 1386 | , readInt8: read_int8 1387 | , readUInt16LE: read_uint16_le 1388 | , readUInt32LE: read_uint32_le 1389 | , readInt16LE: read_int16_le 1390 | , readInt32LE: read_int32_le 1391 | , readFloatLE: read_float_le 1392 | , readDoubleLE: read_double_le 1393 | , readUInt16BE: read_uint16_be 1394 | , readUInt32BE: read_uint32_be 1395 | , readInt16BE: read_int16_be 1396 | , readInt32BE: read_int32_be 1397 | , readFloatBE: read_float_be 1398 | , readDoubleBE: read_double_be 1399 | } 1400 | 1401 | var map = require('./mapped.js') 1402 | 1403 | function read_uint8(target, at) { 1404 | return target[at] 1405 | } 1406 | 1407 | function read_int8(target, at) { 1408 | var v = target[at]; 1409 | return v < 0x80 ? v : v - 0x100 1410 | } 1411 | 1412 | function read_uint16_le(target, at) { 1413 | var dv = map.get(target); 1414 | return dv.getUint16(at + target.byteOffset, true) 1415 | } 1416 | 1417 | function read_uint32_le(target, at) { 1418 | var dv = map.get(target); 1419 | return dv.getUint32(at + target.byteOffset, true) 1420 | } 1421 | 1422 | function read_int16_le(target, at) { 1423 | var dv = map.get(target); 1424 | return dv.getInt16(at + target.byteOffset, true) 1425 | } 1426 | 1427 | function read_int32_le(target, at) { 1428 | var dv = map.get(target); 1429 | return dv.getInt32(at + target.byteOffset, true) 1430 | } 1431 | 1432 | function read_float_le(target, at) { 1433 | var dv = map.get(target); 1434 | return dv.getFloat32(at + target.byteOffset, true) 1435 | } 1436 | 1437 | function read_double_le(target, at) { 1438 | var dv = map.get(target); 1439 | return dv.getFloat64(at + target.byteOffset, true) 1440 | } 1441 | 1442 | function read_uint16_be(target, at) { 1443 | var dv = map.get(target); 1444 | return dv.getUint16(at + target.byteOffset, false) 1445 | } 1446 | 1447 | function read_uint32_be(target, at) { 1448 | var dv = map.get(target); 1449 | return dv.getUint32(at + target.byteOffset, false) 1450 | } 1451 | 1452 | function read_int16_be(target, at) { 1453 | var dv = map.get(target); 1454 | return dv.getInt16(at + target.byteOffset, false) 1455 | } 1456 | 1457 | function read_int32_be(target, at) { 1458 | var dv = map.get(target); 1459 | return dv.getInt32(at + target.byteOffset, false) 1460 | } 1461 | 1462 | function read_float_be(target, at) { 1463 | var dv = map.get(target); 1464 | return dv.getFloat32(at + target.byteOffset, false) 1465 | } 1466 | 1467 | function read_double_be(target, at) { 1468 | var dv = map.get(target); 1469 | return dv.getFloat64(at + target.byteOffset, false) 1470 | } 1471 | 1472 | },{"./mapped.js":18}],20:[function(require,module,exports){ 1473 | module.exports = subarray 1474 | 1475 | function subarray(buf, from, to) { 1476 | return buf.subarray(from || 0, to || buf.length) 1477 | } 1478 | 1479 | },{}],21:[function(require,module,exports){ 1480 | module.exports = to 1481 | 1482 | var base64 = require('base64-js') 1483 | , toutf8 = require('to-utf8') 1484 | 1485 | var encoders = { 1486 | hex: to_hex 1487 | , utf8: to_utf 1488 | , base64: to_base64 1489 | } 1490 | 1491 | function to(buf, encoding) { 1492 | return encoders[encoding || 'utf8'](buf) 1493 | } 1494 | 1495 | function to_hex(buf) { 1496 | var str = '' 1497 | , byt 1498 | 1499 | for(var i = 0, len = buf.length; i < len; ++i) { 1500 | byt = buf[i] 1501 | str += ((byt & 0xF0) >>> 4).toString(16) 1502 | str += (byt & 0x0F).toString(16) 1503 | } 1504 | 1505 | return str 1506 | } 1507 | 1508 | function to_utf(buf) { 1509 | return toutf8(buf) 1510 | } 1511 | 1512 | function to_base64(buf) { 1513 | return base64.fromByteArray(buf) 1514 | } 1515 | 1516 | 1517 | },{"base64-js":11,"to-utf8":12}],22:[function(require,module,exports){ 1518 | module.exports = { 1519 | writeUInt8: write_uint8 1520 | , writeInt8: write_int8 1521 | , writeUInt16LE: write_uint16_le 1522 | , writeUInt32LE: write_uint32_le 1523 | , writeInt16LE: write_int16_le 1524 | , writeInt32LE: write_int32_le 1525 | , writeFloatLE: write_float_le 1526 | , writeDoubleLE: write_double_le 1527 | , writeUInt16BE: write_uint16_be 1528 | , writeUInt32BE: write_uint32_be 1529 | , writeInt16BE: write_int16_be 1530 | , writeInt32BE: write_int32_be 1531 | , writeFloatBE: write_float_be 1532 | , writeDoubleBE: write_double_be 1533 | } 1534 | 1535 | var map = require('./mapped.js') 1536 | 1537 | function write_uint8(target, value, at) { 1538 | return target[at] = value 1539 | } 1540 | 1541 | function write_int8(target, value, at) { 1542 | return target[at] = value < 0 ? value + 0x100 : value 1543 | } 1544 | 1545 | function write_uint16_le(target, value, at) { 1546 | var dv = map.get(target); 1547 | return dv.setUint16(at + target.byteOffset, value, true) 1548 | } 1549 | 1550 | function write_uint32_le(target, value, at) { 1551 | var dv = map.get(target); 1552 | return dv.setUint32(at + target.byteOffset, value, true) 1553 | } 1554 | 1555 | function write_int16_le(target, value, at) { 1556 | var dv = map.get(target); 1557 | return dv.setInt16(at + target.byteOffset, value, true) 1558 | } 1559 | 1560 | function write_int32_le(target, value, at) { 1561 | var dv = map.get(target); 1562 | return dv.setInt32(at + target.byteOffset, value, true) 1563 | } 1564 | 1565 | function write_float_le(target, value, at) { 1566 | var dv = map.get(target); 1567 | return dv.setFloat32(at + target.byteOffset, value, true) 1568 | } 1569 | 1570 | function write_double_le(target, value, at) { 1571 | var dv = map.get(target); 1572 | return dv.setFloat64(at + target.byteOffset, value, true) 1573 | } 1574 | 1575 | function write_uint16_be(target, value, at) { 1576 | var dv = map.get(target); 1577 | return dv.setUint16(at + target.byteOffset, value, false) 1578 | } 1579 | 1580 | function write_uint32_be(target, value, at) { 1581 | var dv = map.get(target); 1582 | return dv.setUint32(at + target.byteOffset, value, false) 1583 | } 1584 | 1585 | function write_int16_be(target, value, at) { 1586 | var dv = map.get(target); 1587 | return dv.setInt16(at + target.byteOffset, value, false) 1588 | } 1589 | 1590 | function write_int32_be(target, value, at) { 1591 | var dv = map.get(target); 1592 | return dv.setInt32(at + target.byteOffset, value, false) 1593 | } 1594 | 1595 | function write_float_be(target, value, at) { 1596 | var dv = map.get(target); 1597 | return dv.setFloat32(at + target.byteOffset, value, false) 1598 | } 1599 | 1600 | function write_double_be(target, value, at) { 1601 | var dv = map.get(target); 1602 | return dv.setFloat64(at + target.byteOffset, value, false) 1603 | } 1604 | 1605 | },{"./mapped.js":18}],23:[function(require,module,exports){ 1606 | module.exports = require("cwise-compiler") 1607 | },{"cwise-compiler":24}],24:[function(require,module,exports){ 1608 | "use strict" 1609 | 1610 | var createThunk = require("./lib/thunk.js") 1611 | 1612 | function Procedure() { 1613 | this.argTypes = [] 1614 | this.shimArgs = [] 1615 | this.arrayArgs = [] 1616 | this.arrayBlockIndices = [] 1617 | this.scalarArgs = [] 1618 | this.offsetArgs = [] 1619 | this.offsetArgIndex = [] 1620 | this.indexArgs = [] 1621 | this.shapeArgs = [] 1622 | this.funcName = "" 1623 | this.pre = null 1624 | this.body = null 1625 | this.post = null 1626 | this.debug = false 1627 | } 1628 | 1629 | function compileCwise(user_args) { 1630 | //Create procedure 1631 | var proc = new Procedure() 1632 | 1633 | //Parse blocks 1634 | proc.pre = user_args.pre 1635 | proc.body = user_args.body 1636 | proc.post = user_args.post 1637 | 1638 | //Parse arguments 1639 | var proc_args = user_args.args.slice(0) 1640 | proc.argTypes = proc_args 1641 | for(var i=0; i0) { 1649 | throw new Error("cwise: pre() block may not reference array args") 1650 | } 1651 | if(i < proc.post.args.length && proc.post.args[i].count>0) { 1652 | throw new Error("cwise: post() block may not reference array args") 1653 | } 1654 | } else if(arg_type === "scalar") { 1655 | proc.scalarArgs.push(i) 1656 | proc.shimArgs.push("scalar" + i) 1657 | } else if(arg_type === "index") { 1658 | proc.indexArgs.push(i) 1659 | if(i < proc.pre.args.length && proc.pre.args[i].count > 0) { 1660 | throw new Error("cwise: pre() block may not reference array index") 1661 | } 1662 | if(i < proc.body.args.length && proc.body.args[i].lvalue) { 1663 | throw new Error("cwise: body() block may not write to array index") 1664 | } 1665 | if(i < proc.post.args.length && proc.post.args[i].count > 0) { 1666 | throw new Error("cwise: post() block may not reference array index") 1667 | } 1668 | } else if(arg_type === "shape") { 1669 | proc.shapeArgs.push(i) 1670 | if(i < proc.pre.args.length && proc.pre.args[i].lvalue) { 1671 | throw new Error("cwise: pre() block may not write to array shape") 1672 | } 1673 | if(i < proc.body.args.length && proc.body.args[i].lvalue) { 1674 | throw new Error("cwise: body() block may not write to array shape") 1675 | } 1676 | if(i < proc.post.args.length && proc.post.args[i].lvalue) { 1677 | throw new Error("cwise: post() block may not write to array shape") 1678 | } 1679 | } else if(typeof arg_type === "object" && arg_type.offset) { 1680 | proc.argTypes[i] = "offset" 1681 | proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset }) 1682 | proc.offsetArgIndex.push(i) 1683 | } else { 1684 | throw new Error("cwise: Unknown argument type " + proc_args[i]) 1685 | } 1686 | } 1687 | 1688 | //Make sure at least one array argument was specified 1689 | if(proc.arrayArgs.length <= 0) { 1690 | throw new Error("cwise: No array arguments specified") 1691 | } 1692 | 1693 | //Make sure arguments are correct 1694 | if(proc.pre.args.length > proc_args.length) { 1695 | throw new Error("cwise: Too many arguments in pre() block") 1696 | } 1697 | if(proc.body.args.length > proc_args.length) { 1698 | throw new Error("cwise: Too many arguments in body() block") 1699 | } 1700 | if(proc.post.args.length > proc_args.length) { 1701 | throw new Error("cwise: Too many arguments in post() block") 1702 | } 1703 | 1704 | //Check debug flag 1705 | proc.debug = !!user_args.printCode || !!user_args.debug 1706 | 1707 | //Retrieve name 1708 | proc.funcName = user_args.funcName || "cwise" 1709 | 1710 | //Read in block size 1711 | proc.blockSize = user_args.blockSize || 64 1712 | 1713 | return createThunk(proc) 1714 | } 1715 | 1716 | module.exports = compileCwise 1717 | 1718 | },{"./lib/thunk.js":26}],25:[function(require,module,exports){ 1719 | "use strict" 1720 | 1721 | var uniq = require("uniq") 1722 | 1723 | // 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) 1724 | // 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. 1725 | function innerFill(order, proc, body) { 1726 | var dimension = order.length 1727 | , nargs = proc.arrayArgs.length 1728 | , has_index = proc.indexArgs.length>0 1729 | , code = [] 1730 | , vars = [] 1731 | , idx=0, pidx=0, i, j 1732 | for(i=0; i=0; --i) { // Start at largest stride and work your way inwards 1750 | idx = order[i] 1751 | code.push(["for(i",i,"=0;i",i," 0) { 1764 | code.push(["index[",pidx,"]-=s",pidx].join("")) 1765 | } 1766 | code.push(["++index[",idx,"]"].join("")) 1767 | } 1768 | code.push("}") 1769 | } 1770 | return code.join("\n") 1771 | } 1772 | 1773 | // 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. 1774 | // TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary. 1775 | // 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. 1776 | function outerFill(matched, order, proc, body) { 1777 | var dimension = order.length 1778 | , nargs = proc.arrayArgs.length 1779 | , blockSize = proc.blockSize 1780 | , has_index = proc.indexArgs.length > 0 1781 | , code = [] 1782 | for(var i=0; i0;){"].join("")) // Iterate back to front 1790 | code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j). 1791 | code.push(["s",order[i],"=j",i].join("")) 1792 | code.push(["j",i,"=0"].join("")) 1793 | code.push(["}else{s",order[i],"=",blockSize].join("")) 1794 | code.push(["j",i,"-=",blockSize,"}"].join("")) 1795 | if(has_index) { 1796 | code.push(["index[",order[i],"]=j",i].join("")) 1797 | } 1798 | } 1799 | for(var i=0; i 0) { 1934 | allEqual = allEqual && summary[i] === summary[i-1] 1935 | } 1936 | } 1937 | if(allEqual) { 1938 | return summary[0] 1939 | } 1940 | return summary.join("") 1941 | } 1942 | 1943 | //Generates a cwise operator 1944 | function generateCWiseOp(proc, typesig) { 1945 | 1946 | //Compute dimension 1947 | // 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. 1948 | var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0 1949 | var orders = new Array(proc.arrayArgs.length) 1950 | var dtypes = new Array(proc.arrayArgs.length) 1951 | for(var i=0; i 0) { 2006 | 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) 2007 | } 2008 | if(proc.indexArgs.length > 0) { 2009 | // Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes. 2010 | var zeros = new Array(dimension) 2011 | for(var i=0; i 3) { 2047 | code.push(processBlock(proc.pre, proc, dtypes)) 2048 | } 2049 | 2050 | //Process body 2051 | var body = processBlock(proc.body, proc, dtypes) 2052 | var matched = countMatches(loopOrders) 2053 | if(matched < dimension) { 2054 | 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. 2055 | } else { 2056 | code.push(innerFill(loopOrders[0], proc, body)) 2057 | } 2058 | 2059 | //Inline epilog 2060 | if(proc.post.body.length > 3) { 2061 | code.push(processBlock(proc.post, proc, dtypes)) 2062 | } 2063 | 2064 | if(proc.debug) { 2065 | console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------") 2066 | } 2067 | 2068 | var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("") 2069 | var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join("")) 2070 | return f() 2071 | } 2072 | module.exports = generateCWiseOp 2073 | 2074 | },{"uniq":27}],26:[function(require,module,exports){ 2075 | "use strict" 2076 | 2077 | // The function below is called when constructing a cwise function object, and does the following: 2078 | // A function object is constructed which accepts as argument a compilation function and returns another function. 2079 | // It is this other function that is eventually returned by createThunk, and this function is the one that actually 2080 | // checks whether a certain pattern of arguments has already been used before and compiles new loops as needed. 2081 | // The compilation passed to the first function object is used for compiling new functions. 2082 | // Once this function object is created, it is called with compile as argument, where the first argument of compile 2083 | // is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise). 2084 | // So createThunk roughly works like this: 2085 | // function createThunk(proc) { 2086 | // var thunk = function(compileBound) { 2087 | // var CACHED = {} 2088 | // return function(arrays and scalars) { 2089 | // if (dtype and order of arrays in CACHED) { 2090 | // var func = CACHED[dtype and order of arrays] 2091 | // } else { 2092 | // var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays) 2093 | // } 2094 | // return func(arrays and scalars) 2095 | // } 2096 | // } 2097 | // return thunk(compile.bind1(proc)) 2098 | // } 2099 | 2100 | var compile = require("./compile.js") 2101 | 2102 | function createThunk(proc) { 2103 | var code = ["'use strict'", "var CACHED={}"] 2104 | var vars = [] 2105 | var thunkName = proc.funcName + "_cwise_thunk" 2106 | 2107 | //Build thunk 2108 | code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join("")) 2109 | var typesig = [] 2110 | var string_typesig = [] 2111 | 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). 2112 | Math.max(0,proc.arrayBlockIndices[i]),proc.arrayBlockIndices[i]<0?(","+proc.arrayBlockIndices[i]+")"):")"].join("")] 2113 | for(var i=0; i 2223 | * License: MIT 2224 | * 2225 | * `npm install is-buffer` 2226 | */ 2227 | 2228 | module.exports = function (obj) { 2229 | return !!( 2230 | obj != null && 2231 | obj.constructor && 2232 | typeof obj.constructor.isBuffer === 'function' && 2233 | obj.constructor.isBuffer(obj) 2234 | ) 2235 | } 2236 | 2237 | },{}],30:[function(require,module,exports){ 2238 | // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 2239 | // 2240 | // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! 2241 | // 2242 | // Originally from narwhal.js (http://narwhaljs.org) 2243 | // Copyright (c) 2009 Thomas Robinson <280north.com> 2244 | // 2245 | // Permission is hereby granted, free of charge, to any person obtaining a copy 2246 | // of this software and associated documentation files (the 'Software'), to 2247 | // deal in the Software without restriction, including without limitation the 2248 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 2249 | // sell copies of the Software, and to permit persons to whom the Software is 2250 | // furnished to do so, subject to the following conditions: 2251 | // 2252 | // The above copyright notice and this permission notice shall be included in 2253 | // all copies or substantial portions of the Software. 2254 | // 2255 | // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2256 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2257 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 2258 | // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2259 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2260 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2261 | 2262 | // when used in node, this will actually load the util module we depend on 2263 | // versus loading the builtin util module as happens otherwise 2264 | // this is a bug in node module loading as far as I am concerned 2265 | var util = require('util/'); 2266 | 2267 | var pSlice = Array.prototype.slice; 2268 | var hasOwn = Object.prototype.hasOwnProperty; 2269 | 2270 | // 1. The assert module provides functions that throw 2271 | // AssertionError's when particular conditions are not met. The 2272 | // assert module must conform to the following interface. 2273 | 2274 | var assert = module.exports = ok; 2275 | 2276 | // 2. The AssertionError is defined in assert. 2277 | // new assert.AssertionError({ message: message, 2278 | // actual: actual, 2279 | // expected: expected }) 2280 | 2281 | assert.AssertionError = function AssertionError(options) { 2282 | this.name = 'AssertionError'; 2283 | this.actual = options.actual; 2284 | this.expected = options.expected; 2285 | this.operator = options.operator; 2286 | if (options.message) { 2287 | this.message = options.message; 2288 | this.generatedMessage = false; 2289 | } else { 2290 | this.message = getMessage(this); 2291 | this.generatedMessage = true; 2292 | } 2293 | var stackStartFunction = options.stackStartFunction || fail; 2294 | 2295 | if (Error.captureStackTrace) { 2296 | Error.captureStackTrace(this, stackStartFunction); 2297 | } 2298 | else { 2299 | // non v8 browsers so we can have a stacktrace 2300 | var err = new Error(); 2301 | if (err.stack) { 2302 | var out = err.stack; 2303 | 2304 | // try to strip useless frames 2305 | var fn_name = stackStartFunction.name; 2306 | var idx = out.indexOf('\n' + fn_name); 2307 | if (idx >= 0) { 2308 | // once we have located the function frame 2309 | // we need to strip out everything before it (and its line) 2310 | var next_line = out.indexOf('\n', idx + 1); 2311 | out = out.substring(next_line + 1); 2312 | } 2313 | 2314 | this.stack = out; 2315 | } 2316 | } 2317 | }; 2318 | 2319 | // assert.AssertionError instanceof Error 2320 | util.inherits(assert.AssertionError, Error); 2321 | 2322 | function replacer(key, value) { 2323 | if (util.isUndefined(value)) { 2324 | return '' + value; 2325 | } 2326 | if (util.isNumber(value) && !isFinite(value)) { 2327 | return value.toString(); 2328 | } 2329 | if (util.isFunction(value) || util.isRegExp(value)) { 2330 | return value.toString(); 2331 | } 2332 | return value; 2333 | } 2334 | 2335 | function truncate(s, n) { 2336 | if (util.isString(s)) { 2337 | return s.length < n ? s : s.slice(0, n); 2338 | } else { 2339 | return s; 2340 | } 2341 | } 2342 | 2343 | function getMessage(self) { 2344 | return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + 2345 | self.operator + ' ' + 2346 | truncate(JSON.stringify(self.expected, replacer), 128); 2347 | } 2348 | 2349 | // At present only the three keys mentioned above are used and 2350 | // understood by the spec. Implementations or sub modules can pass 2351 | // other keys to the AssertionError's constructor - they will be 2352 | // ignored. 2353 | 2354 | // 3. All of the following functions must throw an AssertionError 2355 | // when a corresponding condition is not met, with a message that 2356 | // may be undefined if not provided. All assertion methods provide 2357 | // both the actual and expected values to the assertion error for 2358 | // display purposes. 2359 | 2360 | function fail(actual, expected, message, operator, stackStartFunction) { 2361 | throw new assert.AssertionError({ 2362 | message: message, 2363 | actual: actual, 2364 | expected: expected, 2365 | operator: operator, 2366 | stackStartFunction: stackStartFunction 2367 | }); 2368 | } 2369 | 2370 | // EXTENSION! allows for well behaved errors defined elsewhere. 2371 | assert.fail = fail; 2372 | 2373 | // 4. Pure assertion tests whether a value is truthy, as determined 2374 | // by !!guard. 2375 | // assert.ok(guard, message_opt); 2376 | // This statement is equivalent to assert.equal(true, !!guard, 2377 | // message_opt);. To test strictly for the value true, use 2378 | // assert.strictEqual(true, guard, message_opt);. 2379 | 2380 | function ok(value, message) { 2381 | if (!value) fail(value, true, message, '==', assert.ok); 2382 | } 2383 | assert.ok = ok; 2384 | 2385 | // 5. The equality assertion tests shallow, coercive equality with 2386 | // ==. 2387 | // assert.equal(actual, expected, message_opt); 2388 | 2389 | assert.equal = function equal(actual, expected, message) { 2390 | if (actual != expected) fail(actual, expected, message, '==', assert.equal); 2391 | }; 2392 | 2393 | // 6. The non-equality assertion tests for whether two objects are not equal 2394 | // with != assert.notEqual(actual, expected, message_opt); 2395 | 2396 | assert.notEqual = function notEqual(actual, expected, message) { 2397 | if (actual == expected) { 2398 | fail(actual, expected, message, '!=', assert.notEqual); 2399 | } 2400 | }; 2401 | 2402 | // 7. The equivalence assertion tests a deep equality relation. 2403 | // assert.deepEqual(actual, expected, message_opt); 2404 | 2405 | assert.deepEqual = function deepEqual(actual, expected, message) { 2406 | if (!_deepEqual(actual, expected)) { 2407 | fail(actual, expected, message, 'deepEqual', assert.deepEqual); 2408 | } 2409 | }; 2410 | 2411 | function _deepEqual(actual, expected) { 2412 | // 7.1. All identical values are equivalent, as determined by ===. 2413 | if (actual === expected) { 2414 | return true; 2415 | 2416 | } else if (util.isBuffer(actual) && util.isBuffer(expected)) { 2417 | if (actual.length != expected.length) return false; 2418 | 2419 | for (var i = 0; i < actual.length; i++) { 2420 | if (actual[i] !== expected[i]) return false; 2421 | } 2422 | 2423 | return true; 2424 | 2425 | // 7.2. If the expected value is a Date object, the actual value is 2426 | // equivalent if it is also a Date object that refers to the same time. 2427 | } else if (util.isDate(actual) && util.isDate(expected)) { 2428 | return actual.getTime() === expected.getTime(); 2429 | 2430 | // 7.3 If the expected value is a RegExp object, the actual value is 2431 | // equivalent if it is also a RegExp object with the same source and 2432 | // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). 2433 | } else if (util.isRegExp(actual) && util.isRegExp(expected)) { 2434 | return actual.source === expected.source && 2435 | actual.global === expected.global && 2436 | actual.multiline === expected.multiline && 2437 | actual.lastIndex === expected.lastIndex && 2438 | actual.ignoreCase === expected.ignoreCase; 2439 | 2440 | // 7.4. Other pairs that do not both pass typeof value == 'object', 2441 | // equivalence is determined by ==. 2442 | } else if (!util.isObject(actual) && !util.isObject(expected)) { 2443 | return actual == expected; 2444 | 2445 | // 7.5 For all other Object pairs, including Array objects, equivalence is 2446 | // determined by having the same number of owned properties (as verified 2447 | // with Object.prototype.hasOwnProperty.call), the same set of keys 2448 | // (although not necessarily the same order), equivalent values for every 2449 | // corresponding key, and an identical 'prototype' property. Note: this 2450 | // accounts for both named and indexed properties on Arrays. 2451 | } else { 2452 | return objEquiv(actual, expected); 2453 | } 2454 | } 2455 | 2456 | function isArguments(object) { 2457 | return Object.prototype.toString.call(object) == '[object Arguments]'; 2458 | } 2459 | 2460 | function objEquiv(a, b) { 2461 | if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) 2462 | return false; 2463 | // an identical 'prototype' property. 2464 | if (a.prototype !== b.prototype) return false; 2465 | // if one is a primitive, the other must be same 2466 | if (util.isPrimitive(a) || util.isPrimitive(b)) { 2467 | return a === b; 2468 | } 2469 | var aIsArgs = isArguments(a), 2470 | bIsArgs = isArguments(b); 2471 | if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) 2472 | return false; 2473 | if (aIsArgs) { 2474 | a = pSlice.call(a); 2475 | b = pSlice.call(b); 2476 | return _deepEqual(a, b); 2477 | } 2478 | var ka = objectKeys(a), 2479 | kb = objectKeys(b), 2480 | key, i; 2481 | // having the same number of owned properties (keys incorporates 2482 | // hasOwnProperty) 2483 | if (ka.length != kb.length) 2484 | return false; 2485 | //the same set of keys (although not necessarily the same order), 2486 | ka.sort(); 2487 | kb.sort(); 2488 | //~~~cheap key test 2489 | for (i = ka.length - 1; i >= 0; i--) { 2490 | if (ka[i] != kb[i]) 2491 | return false; 2492 | } 2493 | //equivalent values for every corresponding key, and 2494 | //~~~possibly expensive deep test 2495 | for (i = ka.length - 1; i >= 0; i--) { 2496 | key = ka[i]; 2497 | if (!_deepEqual(a[key], b[key])) return false; 2498 | } 2499 | return true; 2500 | } 2501 | 2502 | // 8. The non-equivalence assertion tests for any deep inequality. 2503 | // assert.notDeepEqual(actual, expected, message_opt); 2504 | 2505 | assert.notDeepEqual = function notDeepEqual(actual, expected, message) { 2506 | if (_deepEqual(actual, expected)) { 2507 | fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); 2508 | } 2509 | }; 2510 | 2511 | // 9. The strict equality assertion tests strict equality, as determined by ===. 2512 | // assert.strictEqual(actual, expected, message_opt); 2513 | 2514 | assert.strictEqual = function strictEqual(actual, expected, message) { 2515 | if (actual !== expected) { 2516 | fail(actual, expected, message, '===', assert.strictEqual); 2517 | } 2518 | }; 2519 | 2520 | // 10. The strict non-equality assertion tests for strict inequality, as 2521 | // determined by !==. assert.notStrictEqual(actual, expected, message_opt); 2522 | 2523 | assert.notStrictEqual = function notStrictEqual(actual, expected, message) { 2524 | if (actual === expected) { 2525 | fail(actual, expected, message, '!==', assert.notStrictEqual); 2526 | } 2527 | }; 2528 | 2529 | function expectedException(actual, expected) { 2530 | if (!actual || !expected) { 2531 | return false; 2532 | } 2533 | 2534 | if (Object.prototype.toString.call(expected) == '[object RegExp]') { 2535 | return expected.test(actual); 2536 | } else if (actual instanceof expected) { 2537 | return true; 2538 | } else if (expected.call({}, actual) === true) { 2539 | return true; 2540 | } 2541 | 2542 | return false; 2543 | } 2544 | 2545 | function _throws(shouldThrow, block, expected, message) { 2546 | var actual; 2547 | 2548 | if (util.isString(expected)) { 2549 | message = expected; 2550 | expected = null; 2551 | } 2552 | 2553 | try { 2554 | block(); 2555 | } catch (e) { 2556 | actual = e; 2557 | } 2558 | 2559 | message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + 2560 | (message ? ' ' + message : '.'); 2561 | 2562 | if (shouldThrow && !actual) { 2563 | fail(actual, expected, 'Missing expected exception' + message); 2564 | } 2565 | 2566 | if (!shouldThrow && expectedException(actual, expected)) { 2567 | fail(actual, expected, 'Got unwanted exception' + message); 2568 | } 2569 | 2570 | if ((shouldThrow && actual && expected && 2571 | !expectedException(actual, expected)) || (!shouldThrow && actual)) { 2572 | throw actual; 2573 | } 2574 | } 2575 | 2576 | // 11. Expected to throw an error: 2577 | // assert.throws(block, Error_opt, message_opt); 2578 | 2579 | assert.throws = function(block, /*optional*/error, /*optional*/message) { 2580 | _throws.apply(this, [true].concat(pSlice.call(arguments))); 2581 | }; 2582 | 2583 | // EXTENSION! This is annoying to write outside this module. 2584 | assert.doesNotThrow = function(block, /*optional*/message) { 2585 | _throws.apply(this, [false].concat(pSlice.call(arguments))); 2586 | }; 2587 | 2588 | assert.ifError = function(err) { if (err) {throw err;}}; 2589 | 2590 | var objectKeys = Object.keys || function (obj) { 2591 | var keys = []; 2592 | for (var key in obj) { 2593 | if (hasOwn.call(obj, key)) keys.push(key); 2594 | } 2595 | return keys; 2596 | }; 2597 | 2598 | },{"util/":34}],31:[function(require,module,exports){ 2599 | if (typeof Object.create === 'function') { 2600 | // implementation from standard node.js 'util' module 2601 | module.exports = function inherits(ctor, superCtor) { 2602 | ctor.super_ = superCtor 2603 | ctor.prototype = Object.create(superCtor.prototype, { 2604 | constructor: { 2605 | value: ctor, 2606 | enumerable: false, 2607 | writable: true, 2608 | configurable: true 2609 | } 2610 | }); 2611 | }; 2612 | } else { 2613 | // old school shim for old browsers 2614 | module.exports = function inherits(ctor, superCtor) { 2615 | ctor.super_ = superCtor 2616 | var TempCtor = function () {} 2617 | TempCtor.prototype = superCtor.prototype 2618 | ctor.prototype = new TempCtor() 2619 | ctor.prototype.constructor = ctor 2620 | } 2621 | } 2622 | 2623 | },{}],32:[function(require,module,exports){ 2624 | // shim for using process in browser 2625 | 2626 | var process = module.exports = {}; 2627 | var queue = []; 2628 | var draining = false; 2629 | var currentQueue; 2630 | var queueIndex = -1; 2631 | 2632 | function cleanUpNextTick() { 2633 | draining = false; 2634 | if (currentQueue.length) { 2635 | queue = currentQueue.concat(queue); 2636 | } else { 2637 | queueIndex = -1; 2638 | } 2639 | if (queue.length) { 2640 | drainQueue(); 2641 | } 2642 | } 2643 | 2644 | function drainQueue() { 2645 | if (draining) { 2646 | return; 2647 | } 2648 | var timeout = setTimeout(cleanUpNextTick); 2649 | draining = true; 2650 | 2651 | var len = queue.length; 2652 | while(len) { 2653 | currentQueue = queue; 2654 | queue = []; 2655 | while (++queueIndex < len) { 2656 | currentQueue[queueIndex].run(); 2657 | } 2658 | queueIndex = -1; 2659 | len = queue.length; 2660 | } 2661 | currentQueue = null; 2662 | draining = false; 2663 | clearTimeout(timeout); 2664 | } 2665 | 2666 | process.nextTick = function (fun) { 2667 | var args = new Array(arguments.length - 1); 2668 | if (arguments.length > 1) { 2669 | for (var i = 1; i < arguments.length; i++) { 2670 | args[i - 1] = arguments[i]; 2671 | } 2672 | } 2673 | queue.push(new Item(fun, args)); 2674 | if (queue.length === 1 && !draining) { 2675 | setTimeout(drainQueue, 0); 2676 | } 2677 | }; 2678 | 2679 | // v8 likes predictible objects 2680 | function Item(fun, array) { 2681 | this.fun = fun; 2682 | this.array = array; 2683 | } 2684 | Item.prototype.run = function () { 2685 | this.fun.apply(null, this.array); 2686 | }; 2687 | process.title = 'browser'; 2688 | process.browser = true; 2689 | process.env = {}; 2690 | process.argv = []; 2691 | process.version = ''; // empty string to avoid regexp issues 2692 | process.versions = {}; 2693 | 2694 | function noop() {} 2695 | 2696 | process.on = noop; 2697 | process.addListener = noop; 2698 | process.once = noop; 2699 | process.off = noop; 2700 | process.removeListener = noop; 2701 | process.removeAllListeners = noop; 2702 | process.emit = noop; 2703 | 2704 | process.binding = function (name) { 2705 | throw new Error('process.binding is not supported'); 2706 | }; 2707 | 2708 | // TODO(shtylman) 2709 | process.cwd = function () { return '/' }; 2710 | process.chdir = function (dir) { 2711 | throw new Error('process.chdir is not supported'); 2712 | }; 2713 | process.umask = function() { return 0; }; 2714 | 2715 | },{}],33:[function(require,module,exports){ 2716 | module.exports = function isBuffer(arg) { 2717 | return arg && typeof arg === 'object' 2718 | && typeof arg.copy === 'function' 2719 | && typeof arg.fill === 'function' 2720 | && typeof arg.readUInt8 === 'function'; 2721 | } 2722 | },{}],34:[function(require,module,exports){ 2723 | (function (process,global){ 2724 | // Copyright Joyent, Inc. and other Node contributors. 2725 | // 2726 | // Permission is hereby granted, free of charge, to any person obtaining a 2727 | // copy of this software and associated documentation files (the 2728 | // "Software"), to deal in the Software without restriction, including 2729 | // without limitation the rights to use, copy, modify, merge, publish, 2730 | // distribute, sublicense, and/or sell copies of the Software, and to permit 2731 | // persons to whom the Software is furnished to do so, subject to the 2732 | // following conditions: 2733 | // 2734 | // The above copyright notice and this permission notice shall be included 2735 | // in all copies or substantial portions of the Software. 2736 | // 2737 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2738 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2739 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 2740 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 2741 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2742 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2743 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 2744 | 2745 | var formatRegExp = /%[sdj%]/g; 2746 | exports.format = function(f) { 2747 | if (!isString(f)) { 2748 | var objects = []; 2749 | for (var i = 0; i < arguments.length; i++) { 2750 | objects.push(inspect(arguments[i])); 2751 | } 2752 | return objects.join(' '); 2753 | } 2754 | 2755 | var i = 1; 2756 | var args = arguments; 2757 | var len = args.length; 2758 | var str = String(f).replace(formatRegExp, function(x) { 2759 | if (x === '%%') return '%'; 2760 | if (i >= len) return x; 2761 | switch (x) { 2762 | case '%s': return String(args[i++]); 2763 | case '%d': return Number(args[i++]); 2764 | case '%j': 2765 | try { 2766 | return JSON.stringify(args[i++]); 2767 | } catch (_) { 2768 | return '[Circular]'; 2769 | } 2770 | default: 2771 | return x; 2772 | } 2773 | }); 2774 | for (var x = args[i]; i < len; x = args[++i]) { 2775 | if (isNull(x) || !isObject(x)) { 2776 | str += ' ' + x; 2777 | } else { 2778 | str += ' ' + inspect(x); 2779 | } 2780 | } 2781 | return str; 2782 | }; 2783 | 2784 | 2785 | // Mark that a method should not be used. 2786 | // Returns a modified function which warns once by default. 2787 | // If --no-deprecation is set, then it is a no-op. 2788 | exports.deprecate = function(fn, msg) { 2789 | // Allow for deprecating things in the process of starting up. 2790 | if (isUndefined(global.process)) { 2791 | return function() { 2792 | return exports.deprecate(fn, msg).apply(this, arguments); 2793 | }; 2794 | } 2795 | 2796 | if (process.noDeprecation === true) { 2797 | return fn; 2798 | } 2799 | 2800 | var warned = false; 2801 | function deprecated() { 2802 | if (!warned) { 2803 | if (process.throwDeprecation) { 2804 | throw new Error(msg); 2805 | } else if (process.traceDeprecation) { 2806 | console.trace(msg); 2807 | } else { 2808 | console.error(msg); 2809 | } 2810 | warned = true; 2811 | } 2812 | return fn.apply(this, arguments); 2813 | } 2814 | 2815 | return deprecated; 2816 | }; 2817 | 2818 | 2819 | var debugs = {}; 2820 | var debugEnviron; 2821 | exports.debuglog = function(set) { 2822 | if (isUndefined(debugEnviron)) 2823 | debugEnviron = process.env.NODE_DEBUG || ''; 2824 | set = set.toUpperCase(); 2825 | if (!debugs[set]) { 2826 | if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { 2827 | var pid = process.pid; 2828 | debugs[set] = function() { 2829 | var msg = exports.format.apply(exports, arguments); 2830 | console.error('%s %d: %s', set, pid, msg); 2831 | }; 2832 | } else { 2833 | debugs[set] = function() {}; 2834 | } 2835 | } 2836 | return debugs[set]; 2837 | }; 2838 | 2839 | 2840 | /** 2841 | * Echos the value of a value. Trys to print the value out 2842 | * in the best way possible given the different types. 2843 | * 2844 | * @param {Object} obj The object to print out. 2845 | * @param {Object} opts Optional options object that alters the output. 2846 | */ 2847 | /* legacy: obj, showHidden, depth, colors*/ 2848 | function inspect(obj, opts) { 2849 | // default options 2850 | var ctx = { 2851 | seen: [], 2852 | stylize: stylizeNoColor 2853 | }; 2854 | // legacy... 2855 | if (arguments.length >= 3) ctx.depth = arguments[2]; 2856 | if (arguments.length >= 4) ctx.colors = arguments[3]; 2857 | if (isBoolean(opts)) { 2858 | // legacy... 2859 | ctx.showHidden = opts; 2860 | } else if (opts) { 2861 | // got an "options" object 2862 | exports._extend(ctx, opts); 2863 | } 2864 | // set default options 2865 | if (isUndefined(ctx.showHidden)) ctx.showHidden = false; 2866 | if (isUndefined(ctx.depth)) ctx.depth = 2; 2867 | if (isUndefined(ctx.colors)) ctx.colors = false; 2868 | if (isUndefined(ctx.customInspect)) ctx.customInspect = true; 2869 | if (ctx.colors) ctx.stylize = stylizeWithColor; 2870 | return formatValue(ctx, obj, ctx.depth); 2871 | } 2872 | exports.inspect = inspect; 2873 | 2874 | 2875 | // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics 2876 | inspect.colors = { 2877 | 'bold' : [1, 22], 2878 | 'italic' : [3, 23], 2879 | 'underline' : [4, 24], 2880 | 'inverse' : [7, 27], 2881 | 'white' : [37, 39], 2882 | 'grey' : [90, 39], 2883 | 'black' : [30, 39], 2884 | 'blue' : [34, 39], 2885 | 'cyan' : [36, 39], 2886 | 'green' : [32, 39], 2887 | 'magenta' : [35, 39], 2888 | 'red' : [31, 39], 2889 | 'yellow' : [33, 39] 2890 | }; 2891 | 2892 | // Don't use 'blue' not visible on cmd.exe 2893 | inspect.styles = { 2894 | 'special': 'cyan', 2895 | 'number': 'yellow', 2896 | 'boolean': 'yellow', 2897 | 'undefined': 'grey', 2898 | 'null': 'bold', 2899 | 'string': 'green', 2900 | 'date': 'magenta', 2901 | // "name": intentionally not styling 2902 | 'regexp': 'red' 2903 | }; 2904 | 2905 | 2906 | function stylizeWithColor(str, styleType) { 2907 | var style = inspect.styles[styleType]; 2908 | 2909 | if (style) { 2910 | return '\u001b[' + inspect.colors[style][0] + 'm' + str + 2911 | '\u001b[' + inspect.colors[style][1] + 'm'; 2912 | } else { 2913 | return str; 2914 | } 2915 | } 2916 | 2917 | 2918 | function stylizeNoColor(str, styleType) { 2919 | return str; 2920 | } 2921 | 2922 | 2923 | function arrayToHash(array) { 2924 | var hash = {}; 2925 | 2926 | array.forEach(function(val, idx) { 2927 | hash[val] = true; 2928 | }); 2929 | 2930 | return hash; 2931 | } 2932 | 2933 | 2934 | function formatValue(ctx, value, recurseTimes) { 2935 | // Provide a hook for user-specified inspect functions. 2936 | // Check that value is an object with an inspect function on it 2937 | if (ctx.customInspect && 2938 | value && 2939 | isFunction(value.inspect) && 2940 | // Filter out the util module, it's inspect function is special 2941 | value.inspect !== exports.inspect && 2942 | // Also filter out any prototype objects using the circular check. 2943 | !(value.constructor && value.constructor.prototype === value)) { 2944 | var ret = value.inspect(recurseTimes, ctx); 2945 | if (!isString(ret)) { 2946 | ret = formatValue(ctx, ret, recurseTimes); 2947 | } 2948 | return ret; 2949 | } 2950 | 2951 | // Primitive types cannot have properties 2952 | var primitive = formatPrimitive(ctx, value); 2953 | if (primitive) { 2954 | return primitive; 2955 | } 2956 | 2957 | // Look up the keys of the object. 2958 | var keys = Object.keys(value); 2959 | var visibleKeys = arrayToHash(keys); 2960 | 2961 | if (ctx.showHidden) { 2962 | keys = Object.getOwnPropertyNames(value); 2963 | } 2964 | 2965 | // IE doesn't make error fields non-enumerable 2966 | // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx 2967 | if (isError(value) 2968 | && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { 2969 | return formatError(value); 2970 | } 2971 | 2972 | // Some type of object without properties can be shortcutted. 2973 | if (keys.length === 0) { 2974 | if (isFunction(value)) { 2975 | var name = value.name ? ': ' + value.name : ''; 2976 | return ctx.stylize('[Function' + name + ']', 'special'); 2977 | } 2978 | if (isRegExp(value)) { 2979 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); 2980 | } 2981 | if (isDate(value)) { 2982 | return ctx.stylize(Date.prototype.toString.call(value), 'date'); 2983 | } 2984 | if (isError(value)) { 2985 | return formatError(value); 2986 | } 2987 | } 2988 | 2989 | var base = '', array = false, braces = ['{', '}']; 2990 | 2991 | // Make Array say that they are Array 2992 | if (isArray(value)) { 2993 | array = true; 2994 | braces = ['[', ']']; 2995 | } 2996 | 2997 | // Make functions say that they are functions 2998 | if (isFunction(value)) { 2999 | var n = value.name ? ': ' + value.name : ''; 3000 | base = ' [Function' + n + ']'; 3001 | } 3002 | 3003 | // Make RegExps say that they are RegExps 3004 | if (isRegExp(value)) { 3005 | base = ' ' + RegExp.prototype.toString.call(value); 3006 | } 3007 | 3008 | // Make dates with properties first say the date 3009 | if (isDate(value)) { 3010 | base = ' ' + Date.prototype.toUTCString.call(value); 3011 | } 3012 | 3013 | // Make error with message first say the error 3014 | if (isError(value)) { 3015 | base = ' ' + formatError(value); 3016 | } 3017 | 3018 | if (keys.length === 0 && (!array || value.length == 0)) { 3019 | return braces[0] + base + braces[1]; 3020 | } 3021 | 3022 | if (recurseTimes < 0) { 3023 | if (isRegExp(value)) { 3024 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); 3025 | } else { 3026 | return ctx.stylize('[Object]', 'special'); 3027 | } 3028 | } 3029 | 3030 | ctx.seen.push(value); 3031 | 3032 | var output; 3033 | if (array) { 3034 | output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); 3035 | } else { 3036 | output = keys.map(function(key) { 3037 | return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); 3038 | }); 3039 | } 3040 | 3041 | ctx.seen.pop(); 3042 | 3043 | return reduceToSingleString(output, base, braces); 3044 | } 3045 | 3046 | 3047 | function formatPrimitive(ctx, value) { 3048 | if (isUndefined(value)) 3049 | return ctx.stylize('undefined', 'undefined'); 3050 | if (isString(value)) { 3051 | var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') 3052 | .replace(/'/g, "\\'") 3053 | .replace(/\\"/g, '"') + '\''; 3054 | return ctx.stylize(simple, 'string'); 3055 | } 3056 | if (isNumber(value)) 3057 | return ctx.stylize('' + value, 'number'); 3058 | if (isBoolean(value)) 3059 | return ctx.stylize('' + value, 'boolean'); 3060 | // For some reason typeof null is "object", so special case here. 3061 | if (isNull(value)) 3062 | return ctx.stylize('null', 'null'); 3063 | } 3064 | 3065 | 3066 | function formatError(value) { 3067 | return '[' + Error.prototype.toString.call(value) + ']'; 3068 | } 3069 | 3070 | 3071 | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { 3072 | var output = []; 3073 | for (var i = 0, l = value.length; i < l; ++i) { 3074 | if (hasOwnProperty(value, String(i))) { 3075 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, 3076 | String(i), true)); 3077 | } else { 3078 | output.push(''); 3079 | } 3080 | } 3081 | keys.forEach(function(key) { 3082 | if (!key.match(/^\d+$/)) { 3083 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, 3084 | key, true)); 3085 | } 3086 | }); 3087 | return output; 3088 | } 3089 | 3090 | 3091 | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { 3092 | var name, str, desc; 3093 | desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; 3094 | if (desc.get) { 3095 | if (desc.set) { 3096 | str = ctx.stylize('[Getter/Setter]', 'special'); 3097 | } else { 3098 | str = ctx.stylize('[Getter]', 'special'); 3099 | } 3100 | } else { 3101 | if (desc.set) { 3102 | str = ctx.stylize('[Setter]', 'special'); 3103 | } 3104 | } 3105 | if (!hasOwnProperty(visibleKeys, key)) { 3106 | name = '[' + key + ']'; 3107 | } 3108 | if (!str) { 3109 | if (ctx.seen.indexOf(desc.value) < 0) { 3110 | if (isNull(recurseTimes)) { 3111 | str = formatValue(ctx, desc.value, null); 3112 | } else { 3113 | str = formatValue(ctx, desc.value, recurseTimes - 1); 3114 | } 3115 | if (str.indexOf('\n') > -1) { 3116 | if (array) { 3117 | str = str.split('\n').map(function(line) { 3118 | return ' ' + line; 3119 | }).join('\n').substr(2); 3120 | } else { 3121 | str = '\n' + str.split('\n').map(function(line) { 3122 | return ' ' + line; 3123 | }).join('\n'); 3124 | } 3125 | } 3126 | } else { 3127 | str = ctx.stylize('[Circular]', 'special'); 3128 | } 3129 | } 3130 | if (isUndefined(name)) { 3131 | if (array && key.match(/^\d+$/)) { 3132 | return str; 3133 | } 3134 | name = JSON.stringify('' + key); 3135 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { 3136 | name = name.substr(1, name.length - 2); 3137 | name = ctx.stylize(name, 'name'); 3138 | } else { 3139 | name = name.replace(/'/g, "\\'") 3140 | .replace(/\\"/g, '"') 3141 | .replace(/(^"|"$)/g, "'"); 3142 | name = ctx.stylize(name, 'string'); 3143 | } 3144 | } 3145 | 3146 | return name + ': ' + str; 3147 | } 3148 | 3149 | 3150 | function reduceToSingleString(output, base, braces) { 3151 | var numLinesEst = 0; 3152 | var length = output.reduce(function(prev, cur) { 3153 | numLinesEst++; 3154 | if (cur.indexOf('\n') >= 0) numLinesEst++; 3155 | return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; 3156 | }, 0); 3157 | 3158 | if (length > 60) { 3159 | return braces[0] + 3160 | (base === '' ? '' : base + '\n ') + 3161 | ' ' + 3162 | output.join(',\n ') + 3163 | ' ' + 3164 | braces[1]; 3165 | } 3166 | 3167 | return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; 3168 | } 3169 | 3170 | 3171 | // NOTE: These type checking functions intentionally don't use `instanceof` 3172 | // because it is fragile and can be easily faked with `Object.create()`. 3173 | function isArray(ar) { 3174 | return Array.isArray(ar); 3175 | } 3176 | exports.isArray = isArray; 3177 | 3178 | function isBoolean(arg) { 3179 | return typeof arg === 'boolean'; 3180 | } 3181 | exports.isBoolean = isBoolean; 3182 | 3183 | function isNull(arg) { 3184 | return arg === null; 3185 | } 3186 | exports.isNull = isNull; 3187 | 3188 | function isNullOrUndefined(arg) { 3189 | return arg == null; 3190 | } 3191 | exports.isNullOrUndefined = isNullOrUndefined; 3192 | 3193 | function isNumber(arg) { 3194 | return typeof arg === 'number'; 3195 | } 3196 | exports.isNumber = isNumber; 3197 | 3198 | function isString(arg) { 3199 | return typeof arg === 'string'; 3200 | } 3201 | exports.isString = isString; 3202 | 3203 | function isSymbol(arg) { 3204 | return typeof arg === 'symbol'; 3205 | } 3206 | exports.isSymbol = isSymbol; 3207 | 3208 | function isUndefined(arg) { 3209 | return arg === void 0; 3210 | } 3211 | exports.isUndefined = isUndefined; 3212 | 3213 | function isRegExp(re) { 3214 | return isObject(re) && objectToString(re) === '[object RegExp]'; 3215 | } 3216 | exports.isRegExp = isRegExp; 3217 | 3218 | function isObject(arg) { 3219 | return typeof arg === 'object' && arg !== null; 3220 | } 3221 | exports.isObject = isObject; 3222 | 3223 | function isDate(d) { 3224 | return isObject(d) && objectToString(d) === '[object Date]'; 3225 | } 3226 | exports.isDate = isDate; 3227 | 3228 | function isError(e) { 3229 | return isObject(e) && 3230 | (objectToString(e) === '[object Error]' || e instanceof Error); 3231 | } 3232 | exports.isError = isError; 3233 | 3234 | function isFunction(arg) { 3235 | return typeof arg === 'function'; 3236 | } 3237 | exports.isFunction = isFunction; 3238 | 3239 | function isPrimitive(arg) { 3240 | return arg === null || 3241 | typeof arg === 'boolean' || 3242 | typeof arg === 'number' || 3243 | typeof arg === 'string' || 3244 | typeof arg === 'symbol' || // ES6 symbol 3245 | typeof arg === 'undefined'; 3246 | } 3247 | exports.isPrimitive = isPrimitive; 3248 | 3249 | exports.isBuffer = require('./support/isBuffer'); 3250 | 3251 | function objectToString(o) { 3252 | return Object.prototype.toString.call(o); 3253 | } 3254 | 3255 | 3256 | function pad(n) { 3257 | return n < 10 ? '0' + n.toString(10) : n.toString(10); 3258 | } 3259 | 3260 | 3261 | var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 3262 | 'Oct', 'Nov', 'Dec']; 3263 | 3264 | // 26 Feb 16:19:34 3265 | function timestamp() { 3266 | var d = new Date(); 3267 | var time = [pad(d.getHours()), 3268 | pad(d.getMinutes()), 3269 | pad(d.getSeconds())].join(':'); 3270 | return [d.getDate(), months[d.getMonth()], time].join(' '); 3271 | } 3272 | 3273 | 3274 | // log is just a thin wrapper to console.log that prepends a timestamp 3275 | exports.log = function() { 3276 | console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); 3277 | }; 3278 | 3279 | 3280 | /** 3281 | * Inherit the prototype methods from one constructor into another. 3282 | * 3283 | * The Function.prototype.inherits from lang.js rewritten as a standalone 3284 | * function (not on Function.prototype). NOTE: If this file is to be loaded 3285 | * during bootstrapping this function needs to be rewritten using some native 3286 | * functions as prototype setup using normal JavaScript does not work as 3287 | * expected during bootstrapping (see mirror.js in r114903). 3288 | * 3289 | * @param {function} ctor Constructor function which needs to inherit the 3290 | * prototype. 3291 | * @param {function} superCtor Constructor function to inherit prototype from. 3292 | */ 3293 | exports.inherits = require('inherits'); 3294 | 3295 | exports._extend = function(origin, add) { 3296 | // Don't do anything if add isn't an object 3297 | if (!add || !isObject(add)) return origin; 3298 | 3299 | var keys = Object.keys(add); 3300 | var i = keys.length; 3301 | while (i--) { 3302 | origin[keys[i]] = add[keys[i]]; 3303 | } 3304 | return origin; 3305 | }; 3306 | 3307 | function hasOwnProperty(obj, prop) { 3308 | return Object.prototype.hasOwnProperty.call(obj, prop); 3309 | } 3310 | 3311 | }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 3312 | },{"./support/isBuffer":33,"_process":32,"inherits":31}],"ndarray-fill":[function(require,module,exports){ 3313 | "use strict" 3314 | 3315 | 3316 | 3317 | var fill = require('cwise/lib/wrapper')({"args":["index","array","scalar"],"pre":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"body":{"body":"{_inline_1_arg1_=_inline_1_arg2_.apply(void 0,_inline_1_arg0_)}","args":[{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_1_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_1_arg2_","lvalue":false,"rvalue":true,"count":1}],"thisVars":[],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"cwise","blockSize":64}) 3318 | 3319 | module.exports = function(array, f) { 3320 | fill(array, f) 3321 | return array 3322 | } 3323 | 3324 | },{"cwise/lib/wrapper":23}],"ndarray":[function(require,module,exports){ 3325 | var iota = require("iota-array") 3326 | var isBuffer = require("is-buffer") 3327 | 3328 | var hasTypedArrays = ((typeof Float64Array) !== "undefined") 3329 | 3330 | function compare1st(a, b) { 3331 | return a[0] - b[0] 3332 | } 3333 | 3334 | function order() { 3335 | var stride = this.stride 3336 | var terms = new Array(stride.length) 3337 | var i 3338 | for(i=0; iMath.abs(this.stride[1]))?[1,0]:[0,1]}})") 3445 | } else if(dimension === 3) { 3446 | code.push( 3447 | "var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\ 3448 | if(s0>s1){\ 3449 | if(s1>s2){\ 3450 | return [2,1,0];\ 3451 | }else if(s0>s2){\ 3452 | return [1,2,0];\ 3453 | }else{\ 3454 | return [1,0,2];\ 3455 | }\ 3456 | }else if(s0>s2){\ 3457 | return [2,0,1];\ 3458 | }else if(s2>s1){\ 3459 | return [0,1,2];\ 3460 | }else{\ 3461 | return [0,2,1];\ 3462 | }}})") 3463 | } 3464 | } else { 3465 | code.push("ORDER})") 3466 | } 3467 | } 3468 | 3469 | //view.set(i0, ..., v): 3470 | code.push( 3471 | "proto.set=function "+className+"_set("+args.join(",")+",v){") 3472 | if(useGetters) { 3473 | code.push("return this.data.set("+index_str+",v)}") 3474 | } else { 3475 | code.push("return this.data["+index_str+"]=v}") 3476 | } 3477 | 3478 | //view.get(i0, ...): 3479 | code.push("proto.get=function "+className+"_get("+args.join(",")+"){") 3480 | if(useGetters) { 3481 | code.push("return this.data.get("+index_str+")}") 3482 | } else { 3483 | code.push("return this.data["+index_str+"]}") 3484 | } 3485 | 3486 | //view.index: 3487 | code.push( 3488 | "proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}") 3489 | 3490 | //view.hi(): 3491 | code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+ 3492 | indices.map(function(i) { 3493 | return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("") 3494 | }).join(",")+","+ 3495 | indices.map(function(i) { 3496 | return "this.stride["+i + "]" 3497 | }).join(",")+",this.offset)}") 3498 | 3499 | //view.lo(): 3500 | var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" }) 3501 | var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" }) 3502 | code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(",")) 3503 | for(var i=0; i=0){\ 3506 | d=i"+i+"|0;\ 3507 | b+=c"+i+"*d;\ 3508 | a"+i+"-=d}") 3509 | } 3510 | code.push("return new "+className+"(this.data,"+ 3511 | indices.map(function(i) { 3512 | return "a"+i 3513 | }).join(",")+","+ 3514 | indices.map(function(i) { 3515 | return "c"+i 3516 | }).join(",")+",b)}") 3517 | 3518 | //view.step(): 3519 | code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+ 3520 | indices.map(function(i) { 3521 | return "a"+i+"=this.shape["+i+"]" 3522 | }).join(",")+","+ 3523 | indices.map(function(i) { 3524 | return "b"+i+"=this.stride["+i+"]" 3525 | }).join(",")+",c=this.offset,d=0,ceil=Math.ceil") 3526 | for(var i=0; i=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}") 3562 | } 3563 | code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}") 3564 | 3565 | //Add return statement 3566 | code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+ 3567 | indices.map(function(i) { 3568 | return "shape["+i+"]" 3569 | }).join(",")+","+ 3570 | indices.map(function(i) { 3571 | return "stride["+i+"]" 3572 | }).join(",")+",offset)}") 3573 | 3574 | //Compile procedure 3575 | var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n")) 3576 | return procedure(CACHED_CONSTRUCTORS[dtype], order) 3577 | } 3578 | 3579 | function arrayDType(data) { 3580 | if(isBuffer(data)) { 3581 | return "buffer" 3582 | } 3583 | if(hasTypedArrays) { 3584 | switch(Object.prototype.toString.call(data)) { 3585 | case "[object Float64Array]": 3586 | return "float64" 3587 | case "[object Float32Array]": 3588 | return "float32" 3589 | case "[object Int8Array]": 3590 | return "int8" 3591 | case "[object Int16Array]": 3592 | return "int16" 3593 | case "[object Int32Array]": 3594 | return "int32" 3595 | case "[object Uint8Array]": 3596 | return "uint8" 3597 | case "[object Uint16Array]": 3598 | return "uint16" 3599 | case "[object Uint32Array]": 3600 | return "uint32" 3601 | case "[object Uint8ClampedArray]": 3602 | return "uint8_clamped" 3603 | } 3604 | } 3605 | if(Array.isArray(data)) { 3606 | return "array" 3607 | } 3608 | return "generic" 3609 | } 3610 | 3611 | var CACHED_CONSTRUCTORS = { 3612 | "float32":[], 3613 | "float64":[], 3614 | "int8":[], 3615 | "int16":[], 3616 | "int32":[], 3617 | "uint8":[], 3618 | "uint16":[], 3619 | "uint32":[], 3620 | "array":[], 3621 | "uint8_clamped":[], 3622 | "buffer":[], 3623 | "generic":[] 3624 | } 3625 | 3626 | ;(function() { 3627 | for(var id in CACHED_CONSTRUCTORS) { 3628 | CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1)) 3629 | } 3630 | }); 3631 | 3632 | function wrappedNDArrayCtor(data, shape, stride, offset) { 3633 | if(data === undefined) { 3634 | var ctor = CACHED_CONSTRUCTORS.array[0] 3635 | return ctor([]) 3636 | } else if(typeof data === "number") { 3637 | data = [data] 3638 | } 3639 | if(shape === undefined) { 3640 | shape = [ data.length ] 3641 | } 3642 | var d = shape.length 3643 | if(stride === undefined) { 3644 | stride = new Array(d) 3645 | for(var i=d-1, sz=1; i>=0; --i) { 3646 | stride[i] = sz 3647 | sz *= shape[i] 3648 | } 3649 | } 3650 | if(offset === undefined) { 3651 | offset = 0 3652 | for(var i=0; i