text: (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  /* jshint node: true */
  /* jshint browser:true */
  "use strict";
  
  var ObjMtlLoader = require('obj-mtl-loader');
  var PC2Loader = require('parse-pc2');
  var Model = require('./lib/model');
  var request = require('xhr-request');
  var arrayBufferToBuffer = require('arraybuffer-to-buffer');
  var assert = require('chai').assert;
  
  var glContext   = require('gl-context');
  var fit         = require('canvas-fit');
  
  var Geom    = require('gl-geometry');
  var glClear   = require('gl-clear');
  var glShader = require('gl-shader');
  
  var mat4    = require('gl-mat4');
  var vec3    = require('gl-vec3');
  var quat    = require('gl-quat');
  
  var createOrbitCamera = require("orbit-camera");
  var GPControls = require('gp-controls');
  
  var intersect = require('ray-triangle-intersection');
  var computeNormals = require('normals');
  
  var gamepad = GPControls({
      '<axis-left-x>': 'x',
  	'<axis-left-y>': 'y',
  	'<action 1>': 'plant'
  });
  var keyPressed = require('key-pressed');
  
  // Creates a canvas element and attaches
  // it to the <body> on your DOM.
  var canvas = document.body.appendChild(document.createElement('canvas'));
  
  // A small convenience function for creating
  // a new WebGL context - the "render" function
  // supplied here is called every frame to draw
  // to the screen.
  var gl = glContext(canvas, render);
  
  // Resizes the <canvas> to fully fit the window
  // whenever the window is resized.
  window.addEventListener('resize', fit(canvas), false);
  
  var clear = glClear({ color: [0, 0, 0, 1], depth: true });
  gl.enable(gl.CULL_FACE);
  gl.enable(gl.DEPTH_TEST);
  
  var shader = glShader(gl,
      "#define GLSLIFY 1\nprecision mediump float;\r\n\r\nattribute vec3 position;\r\nattribute vec3 normal;\r\n\r\nuniform mat4 normalMatrix;\r\nuniform mat4 proj;\r\nuniform mat4 view;\r\nuniform mat4 model;\r\n\r\nuniform vec3 color;\r\n\r\nvarying vec3 v_normal;\r\n\r\nvoid main() {\r\n  gl_Position = (\r\n    proj *\r\n    view *\r\n\tmodel *\r\n    vec4(position, 1.0)\r\n  );\r\n  v_normal = (normalMatrix * vec4(normal, 1.0)).xyz;\r\n}\r\n",
  	"#define GLSLIFY 1\nprecision mediump float;\r\nuniform vec3 v_color;\r\nvarying vec3 v_normal;\r\n\r\nvoid main() {\r\n\r\n\tvec3 normal = normalize(v_normal);\r\n\tvec4 color = vec4(0., 0., 0., 0.);\r\n\tvec4 diffuse = vec4(0., 0., 0., 1.);\r\n\tdiffuse.rgb = v_color.rgb;\r\n\tdiffuse.xyz *= max(dot(normal,vec3(0.,0.,1.)), 0.);\r\n\tcolor.xyz += diffuse.xyz;\r\n\tcolor = vec4(color.rgb, 1.0);\r\n\tgl_FragColor = color;\r\n\r\n  //gl_FragColor = vec4(color, 1.0);\r\n}\r\n");
  
  var eye = [0, 0, -35];
  var center = [0, 0, 0];
  var up = [1, 0, 0];
  var camera = createOrbitCamera(eye, center, up);
  
  console.log('WebGL setup done, loading assets...');
  var globe = null, cloud = null;
  loadAssets();
  
  var tree;
  var animation;
  var animationLoaded = false;
  
  function loadAssets(globeLoaded) {
  
  	// Load globe
  	new ObjMtlLoader().load('./assets/globe.obj', './assets/globe.mtl', function(err, objAndMtl) {
  		if (err) {
  			console.log(err);
  			throw err;
  		}
  
  		console.log('Globe loaded');
  		
  		globe = new Model(objAndMtl, gl);
  		globe.setup(globe.geom.data.rawVertices);
  		globe.model = mat4.create();
  	});
  	
  	// Load cloud
  	new ObjMtlLoader().load('./assets/cloud.obj', './assets/cloud.mtl', function(err, objAndMtl) {
  		if (err) {
  			console.log(err);
  			throw err;
  		}
  
  		console.log('Cloud loaded');
  		
  		cloud = new Model(objAndMtl, gl);
  		cloud.setup(cloud.geom.data.rawVertices);
  	});
  	
  	loadTree();
  }
  
  var cloudsPos = [
  	[ 0, 15, 10 ],
  	[ -10, -13, 11 ],
  	[ -10, -8, 10 ],
  	[ -15, 8, 10 ],
  	[ 0, -12, -8 ],
  	[ +8, 12, -2 ]
  ];
  
  var treePos = [];
  
  var lastPlant = 0;
  
  var lastDate = Date.now();
  var lastx=0, lasty=0;
  function render() {
  
  	// Compute the time elasped since last render (in ms)
  	var now = Date.now();
  	var step = now - lastDate;
  	lastDate = now;
  	
  	// Time coefficient. 1 is the base, will double if frame rate doubles
  	var coef = (step === 0) ? 1 : (18/step);
  	
  	var width = canvas.width;
  	var height = canvas.height;
  
  	gl.viewport(0, 0, width, height);
  	clear(gl);
  
  	var proj = mat4.create();
  	mat4.perspective(proj, Math.PI / 4, width / height, 0.001, 1000);
  
  	if (globe !== null) {
  	
  		var view = camera.view();
  		
  		// Player actions
  		var plantPressed = false;
  		var padx = 0, pady = 0;
  
  		// Gamepad
  		gamepad.poll();
  		if (gamepad.enabled) {
  			padx = Math.abs(gamepad.inputs.x) < 0.25 ? 0 : gamepad.inputs.x;
  			pady = Math.abs(gamepad.inputs.y) < 0.25 ? 0 : gamepad.inputs.y;
  			plantPressed = gamepad.inputs.plant.pressed;
  		}
  
  		// Keyboard
  		if (keyPressed("<left>")) {
  			padx = -1;
  		}
  		if (keyPressed("<right>")) {
  			padx = +1;
  		}
  		if (keyPressed("<up>")) {
  			pady = -1;
  		}
  		if (keyPressed("<down>")) {
  			pady = +1;
  		}
  		plantPressed |= keyPressed("<space>");
  
  		// Animate camera
  		var x=padx/(100*coef),y=pady/(100*coef);
  		camera.rotate([x,y], [0,0]);
  		lastx = x;
  		lasty = y;
  		
  		if (plantPressed) {
  
  			// Not more than once per second
  			if (Date.now() - lastPlant > 500) {
  				lastPlant = Date.now();
  
  				console.log('Plant!');
  				
  				var pt = [0, 0, 0];
  				
  				var invView = mat4.create();
  				mat4.invert(invView, view);
  				
  				var dir = vec3.create();
  				//vec3.set(dir, eye[0], eye[1], eye[2]);
  				var modelDir = vec3.create();
  				vec3.transformMat4(modelDir, dir, invView);
  				vec3.scale(modelDir, modelDir, -0.5);
  				
  				// Search for an intersection with a globe triangle
  				var data = globe.geom.data;
  				var faces = data.rawFaces;
  				var intersection = null;
  				var intersected;
  				for (var f=0; f<faces.length; f++) {
  					var i0 = faces[f][0], i1 = faces[f][1], i2 = faces[f][2];
  					var tri = [ data.rawVertices[i0], data.rawVertices[i1], data.rawVertices[i2] ];
  					intersection = intersect([], pt, modelDir, tri);
  					if (intersection !== null) {
  					intersected = f;
  						break;
  					}
  				}
  				
  				if (intersection !== null) {
  					console.log('Intersection found:', intersection);
  					treePos.push({'pos': intersection, 'intersected': intersected, 'frame': 0});
  				}
  			}
  		}
  		
  		// Add a constant rotation
  		camera.rotate([0.0008 / coef,0], [0,0]);
  
  		// Compute matrices
  		// See http://stackoverflow.com/a/21079741/38096
  		var normalMatrix = mat4.create();
  		var temp = mat4.create();
  		mat4.invert(temp, view);
  		mat4.transpose(normalMatrix, temp);
  
  		// Set up shader
  		globe.geom.bind(shader);
  		shader.uniforms.proj = proj;
  		shader.uniforms.view = view;
  		shader.uniforms.normalMatrix = normalMatrix;
  
  		shader.uniforms.model = globe.model;
  		globe.draw(shader);
  		globe.geom.unbind();
  		
  		cloud.geom.bind(shader);
  		shader.uniforms.proj = proj;
  		shader.uniforms.view = view;
  		shader.uniforms.normalMatrix = normalMatrix;
  
  		for (var cl=0; cl<cloudsPos.length; cl++) {
  			var cloudModel = mat4.create();
  			var posarr = cloudsPos[cl];
  			var vpos = vec3.create();
  			vec3.set(vpos, posarr[0], posarr[1], posarr[2]);
  			mat4.translate(cloudModel, mat4.create(), vpos);
  			shader.uniforms.model = cloudModel;
  			cloud.draw(shader);
  		}
  		cloud.geom.unbind();
  		
  		if (tree !== null && treePos.length > 0 && animationLoaded) {
  
  			// No culling for trees since leaves are only one polygon wide
  			gl.disable(gl.CULL_FACE);
  
  			for (var tr=0; tr<treePos.length; tr++) {
  
  				var data = tree.geom.data;
  
  				// Compute current animation state
  				var currentFrame = Math.floor(treePos[tr].frame);
  				if (currentFrame < animation.length - 1) {
  					treePos[tr].frame += step * 0.02;
  				} else {
  					// Just to be on the safe side
  					currentFrame = animation.length - 1;
  				}
  
  				var currentFrameVertices = animation[currentFrame];
  				assert.isArray(currentFrameVertices);
  				assert.equal(currentFrameVertices.length, data.baseVertices.length);
  
  				// Update model with animation data
  				tree.setup(currentFrameVertices);
  
  				tree.geom.bind(shader);
  				shader.uniforms.proj = proj;
  				shader.uniforms.view = view;
  
  				// Build a rotation matrix to rotate the tree such that it is aligned with the triangle normal
  				var triNormal = globe.geom.data.rawNormals[treePos[tr].intersected];
  				var normal = vec3.fromValues(triNormal[0], triNormal[1], triNormal[2]);
  				vec3.normalize(normal, normal);
  				
  				// Now that intersection point was computed, we do not take camera into account anymore;
  				// coordinates are expressed in the globe reference frame
  				// (which sits at the origin, untransformed)
  
  				// The intersection point (will be the base of the tree)
  				var vpos = vec3.fromValues(treePos[tr].pos[0], treePos[tr].pos[1], treePos[tr].pos[2]);
  
  				// Build a rotation matrix from the tree up vector to the vpos vector (the "local up")
  				var localUp = vec3.create();
  				vec3.normalize(localUp, vpos);
  				
  				// Should be the same computation as quat.rotationTo(couldn't get rotationTo to work)
  				// Source: http://forums.cgsociety.org/archive/index.php?t-741227.html
  				var z2 = vec3.fromValues(0,1,0); // y is up in Blender (for our tree anyway)
  				var z1 = normal; //localUp;
  				
  				var theRotAxis = vec3.create();
  				vec3.cross(theRotAxis, z2, z1);
  				vec3.normalize(theRotAxis, theRotAxis);
  				
  				var theAngle = Math.acos(vec3.dot(z2, z1));
  
  				var theQuat = quat.create();
  				quat.setAxisAngle(theQuat, theRotAxis, theAngle);
  				
  				var rot = mat4.create();
  				mat4.fromQuat(rot, theQuat);
  				
  				// Build a translation matrix to go from the origin to the intersection point
  				var translate = mat4.create();
  				mat4.translate(translate, translate, vpos);
  				
  				// Scale matrix (tree is too big wrt the globe)
  				var scale = mat4.create();
  				mat4.scale(scale, scale, vec3.fromValues(0.15,0.15,0.15));
  
  				// Compose transformations
  				var treeModel = mat4.create();
  				mat4.multiply(treeModel, treeModel, translate);
  				mat4.multiply(treeModel, treeModel, rot);
  				mat4.multiply(treeModel, treeModel, scale);
  
  				// Draw using this model transformation
  				shader.uniforms.model = treeModel;
  				
  				// Since model matrix is not identity,
  				// normalMatrix must be recomputed for each tree
  				shader.uniforms.normalMatrix = computeNormalMatrix(view, treeModel);
  				
  				tree.draw(shader);
  
  				tree.geom.unbind();
  			}
  
  			gl.enable(gl.CULL_FACE);
  		}
  	}
  }
  
  function computeNormalMatrix(view, model) {
  	var viewModel = mat4.create();
  	mat4.multiply(viewModel, view, model);
  	
  	var temp = mat4.create();
  	mat4.invert(temp, viewModel);
  
  	var normalMatrix = mat4.create();
  	mat4.transpose(normalMatrix, temp);
  	return normalMatrix;
  }
  		
  function loadTree() {
  
  	var objLoader = new ObjMtlLoader();
  	objLoader.load('./assets/palmtree_animated_joined.obj', './assets/palmtree_animated_joined.mtl', function(err, objAndMtl) {
  		if (err) {
  			console.log(err);
  			throw err;
  		}
  		
  		console.log('Tree model loaded');
  
  		tree = new Model(objAndMtl, gl);
  		tree.setup(tree.geom.data.rawVertices);
  	});
  
  	var pc2Loader = new PC2Loader.StreamingParser();
  	pc2Loader.on('readable', function() {
  		var pc2Data = pc2Loader.read();
  		if (pc2Data) {
  			console.log('Tree animation loaded');
  			animation = pc2Data.frames;
  			animationLoaded = true;
  		}
  	});
  
  	// binary-xhr works, too
  	request('./assets/palmtree_animated_joined.pc2', {
  		responseType: 'arraybuffer'
  	}, function (err, data) {
  		if (err) {
  			console.log(err);
  			throw err;
  		}
  
  		// Cannot consume ArrayBuffer content directly...
  		// See http://www.html5rocks.com/en/tutorials/webgl/typed_arrays/
  		var dataBuffer = arrayBufferToBuffer(data);
  		pc2Loader.write(dataBuffer);
  	});
  }
  },{"./lib/model":2,"arraybuffer-to-buffer":6,"canvas-fit":13,"chai":14,"gl-clear":61,"gl-context":64,"gl-geometry":66,"gl-mat4":78,"gl-quat":113,"gl-shader":130,"gl-vec3":152,"gp-controls":192,"key-pressed":202,"normals":205,"obj-mtl-loader":206,"orbit-camera":209,"parse-pc2":212,"ray-triangle-intersection":244,"xhr-request":274}],2:[function(require,module,exports){
  /* jshint node: true */
  /* jshint browser:true */
  "use strict";
  
  var Geom    = require('gl-geometry');
  var assert = require('chai').assert;
  var computeNormals = require('normals');
  
  /* A model loaded from an .obj + .mtl and ready to br drawn */
  function Model(objAndMtl, gl) {
  
  	this.gl = gl;
  
  	// Convert data to the expected format
  	var vertices = convertVertices(objAndMtl.vertices);
  	var tuple = convertFaces(objAndMtl.faces);
  	var rawFaces = tuple[0], rawNormals = tuple[1]; // Could use destructuring assignment. Not sure of its availability
  	
  	// Duplicate vertices and normals indexes since there is one normal per face
  	// (so a member of "vertices" will have as many normals as faces it contributes to)
  	// See https://forums.khronos.org/showthread.php/7063-Texture-coordinates-per-face-index-instead-of-per-vertex
  	// Having separate faces is mndatory to get a "flat" shading
  	// TODO Have a look at hughsk/unindex-mesh
  	// Note that we will not actually use the .obj normals since the .pc2 does not provide them for intermediary poses
  	// To keep things simple each face "f" (numbered from 0) will use position and normal at index f, f+1 and f+2
  	var faceIndices = [];
  	for (var i=0; i<rawFaces.length; i++) {
  		faceIndices.push([3*i, 3*i+1, 3*i+2]);
  	}
  	assert.equal(faceIndices.length, objAndMtl.faces.length);
  	assert.equal(faceIndices.length, rawFaces.length);
  
  	// Build rendering model (manage VAO, buffers and draw calls)
  	// Note that this object will not actually be drawn (see render)
  	this.geom = Geom(gl).attr('position', vertices).faces(faceIndices);
  	
  	// Attach topology and materials data to model for later use
  	var data = {};
  	data.rawVertices = vertices;
  	data.rawFaces = rawFaces;
  	data.rawNormals = objAndMtl.normals;
  	data.faceNormals = rawNormals;
  	data.faceIndices = faceIndices;
  	data.materials = objAndMtl.materials;
  	data.facesMaterials = objAndMtl.facesMaterialsIndex;
  	this.geom.data = data;
  	
  	console.log('Raw model statistics: ' + vertices.length + ' vertices, ' + rawFaces.length + ' faces, ' + data.materials.length + ' materials');
  	console.log('Materials:', data.materials);
  	console.log('Faces Materials:', data.facesMaterials);
  
  	// We want to be able to access those by name
  	for (var j=0; j<data.materials.length; j++) {
  		var material = data.materials[j];
  		data.materials[material.name] = material;
  	}
  
  	// Debugging purpose
  	data.baseVertices = vertices;
  
  	console.log('Model set up');
  }
  
  // Call this to animate vertices (and at least once to compute normals)
  Model.prototype.setup = function(currentFrameVertices) {
  	var data = this.geom.data;
  
  	// Duplicate positions (see comments in onModelLoaded)
  	var positions = [];
  	for (var j=0; j<data.rawFaces.length; j++) {
  		var idx = data.rawFaces[j];
  		positions.push(currentFrameVertices[idx[0]]);
  		positions.push(currentFrameVertices[idx[1]]);
  		positions.push(currentFrameVertices[idx[2]]);
  	}
  	
  	// Compute normals per vertex
  	var faceNormals = computeNormals.faceNormals(data.faceIndices, positions);
  	var normals = [];
  	for (var k=0; k<data.rawFaces.length; k++) {
  		var faceNormal = faceNormals[k];
  		normals.push(faceNormal);
  		normals.push(faceNormal);
  		normals.push(faceNormal);
  	}
  
  	// Update model with animation data
  	this.geom.attr('position', positions).attr('normal', normals);
  };
  
  Model.prototype.draw = function(shader) {
  
  	// Subdivide draw calls by material (we asked the obj exporter to sort faces accordingly)
  	var data = this.geom.data;
  	var fmat = data.facesMaterials;
  	for (var i=0; i<fmat.length; i++) {
  		var facesInfo = fmat[i];
  		var firstFace = facesInfo.materialStartIndex;
  		var nbFaces = ((i == fmat.length - 1) ? (data.faceIndices.length) : fmat[i + 1].materialStartIndex) - firstFace;
  
  		var material = data.materials[facesInfo.materialName];
  		var diffuse = material.diffuse;
  		var color = [ parseFloat(diffuse[0]), parseFloat(diffuse[1]), parseFloat(diffuse[2]) ];
  		shader.uniforms.v_color = color;
  
  		var start = firstFace * 3;
  		var stop = start + nbFaces * 3;
  
  		this.geom.draw(this.gl.TRIANGLES, start, stop);
  	}
  };
  
  // Convert vertices returned by obj-mtl-loader to a format suitable for gl-geometry
  function convertVertices(vertices) {
  	assert.isArray(vertices);
  
  	if (vertices.length === 0) {
  		return vertices;
  	}
  	
  	assert.isArray(vertices[0]);
  	
  	if (vertices[0].length === 3) {
  		return vertices;
  	}
  	
  	if (vertices[0].length === 4) {
  		// Only keep the first 3 components for each vertex
  		var result = [];
  		for (var i=0; i<vertices.length; i++) {
  			result.push([ vertices[i][0], vertices[i][1], vertices[i][2] ]);
  		}
  		return result;
  	}
  
  	throw 'Unhandled vertices format';
  }
  
  // Convert vertice and normal indexes returned by obj-mtl-loader to a format suitable for gl-geometry
  function convertFaces(faces) {
  	assert.isArray(faces);
  	
  	var verticesIndex = [];
  	var normalsIndex = [];
  	for (var i=0; i<faces.length; i++) {
  		var indices	= faces[i].indices;
  		verticesIndex.push([ parseInt(indices[0])-1, parseInt(indices[1])-1, parseInt(indices[2])-1 ]);
  		normalsIndex.push(parseInt(faces[i].normal)-1);
  	}
  
  	return [verticesIndex, normalsIndex];
  }
  
  module.exports = Model;
  },{"chai":14,"gl-geometry":66,"normals":205}],3:[function(require,module,exports){
  var padLeft = require('pad-left')
  
  module.exports = addLineNumbers
  function addLineNumbers (string, start, delim) {
    start = typeof start === 'number' ? start : 1
    delim = delim || ': '
  
    var lines = string.split(/\r?\n/)
    var totalDigits = String(lines.length + start - 1).length
    return lines.map(function (line, i) {
      var c = i + start
      var digits = String(c).length
      var prefix = padLeft(c, totalDigits - digits)
      return prefix + delim + line
    }).join('\n')
  }
  
  },{"pad-left":210}],4:[function(require,module,exports){
  var dtype = require('dtype')
  
  module.exports = pack
  
  function pack(arr, type) {
    type = type || 'float32'
  
    if (!arr[0] || !arr[0].length) {
      return arr
    }
  
    var Arr = typeof type === 'string'
      ? dtype(type)
      : type
  
    var dim = arr[0].length
    var out = new Arr(arr.length * dim)
    var k = 0
  
    for (var i = 0; i < arr.length; i++)
    for (var j = 0; j < dim; j++) {
      out[k++] = arr[i][j]
    }
  
    return out
  }
  
  },{"dtype":5}],5:[function(require,module,exports){
  (function (Buffer){
  module.exports = function(dtype) {
    switch (dtype) {
      case 'int8':
        return Int8Array
      case 'int16':
        return Int16Array
      case 'int32':
        return Int32Array
      case 'uint8':
        return Uint8Array
      case 'uint16':
        return Uint16Array
      case 'uint32':
        return Uint32Array
      case 'float32':
        return Float32Array
      case 'float64':
        return Float64Array
      case 'array':
        return Array
      case 'uint8_clamped':
        return Uint8ClampedArray
      case 'generic':
      case 'data':
      case 'dataview':
        return ArrayBuffer
      case 'buffer':
        if (typeof Buffer === "undefined") return ArrayBuffer
        return Buffer
    }
  }
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":12}],6:[function(require,module,exports){
  (function (Buffer){
  (function(root) {
  
    function ArrayBufferToBuffer(ab) {
      var buffer = new Buffer(ab.byteLength);
      var view = new Uint8Array(ab);
      for (var i = 0; i < buffer.length; ++i) {
          buffer[i] = view[i];
      }
      return buffer;
    }
  
    if (typeof exports !== 'undefined') {
      if (typeof module !== 'undefined' && module.exports) {
        exports = module.exports = ArrayBufferToBuffer;
      }
      exports.ArrayBufferToBuffer = ArrayBufferToBuffer;
    } else if (typeof define === 'function' && define.amd) {
      define([], function() {
        return ArrayBufferToBuffer;
      });
    } else {
      root.ArrayBufferToBuffer = ArrayBufferToBuffer;
    }
  
  })(this);
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":12}],7:[function(require,module,exports){
  /*!
   * assertion-error
   * Copyright(c) 2013 Jake Luer <jake@qualiancy.com>
   * MIT Licensed
   */
  
  /*!
   * Return a function that will copy properties from
   * one object to another excluding any originally
   * listed. Returned function will create a new `{}`.
   *
   * @param {String} excluded properties ...
   * @return {Function}
   */
  
  function exclude () {
    var excludes = [].slice.call(arguments);
  
    function excludeProps (res, obj) {
      Object.keys(obj).forEach(function (key) {
        if (!~excludes.indexOf(key)) res[key] = obj[key];
      });
    }
  
    return function extendExclude () {
      var args = [].slice.call(arguments)
        , i = 0
        , res = {};
  
      for (; i < args.length; i++) {
        excludeProps(res, args[i]);
      }
  
      return res;
    };
  };
  
  /*!
   * Primary Exports
   */
  
  module.exports = AssertionError;
  
  /**
   * ### AssertionError
   *
   * An extension of the JavaScript `Error` constructor for
   * assertion and validation scenarios.
   *
   * @param {String} message
   * @param {Object} properties to include (optional)
   * @param {callee} start stack function (optional)
   */
  
  function AssertionError (message, _props, ssf) {
    var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
      , props = extend(_props || {});
  
    // default values
    this.message = message || 'Unspecified AssertionError';
    this.showDiff = false;
  
    // copy from properties
    for (var key in props) {
      this[key] = props[key];
    }
  
    // capture stack trace
    ssf = ssf || arguments.callee;
    if (ssf && Error.captureStackTrace) {
      Error.captureStackTrace(this, ssf);
    } else {
      this.stack = new Error().stack;
    }
  }
  
  /*!
   * Inherit from Error.prototype
   */
  
  AssertionError.prototype = Object.create(Error.prototype);
  
  /*!
   * Statically set name
   */
  
  AssertionError.prototype.name = 'AssertionError';
  
  /*!
   * Ensure correct constructor
   */
  
  AssertionError.prototype.constructor = AssertionError;
  
  /**
   * Allow errors to be converted to JSON for static transfer.
   *
   * @param {Boolean} include stack (default: `true`)
   * @return {Object} object that can be `JSON.stringify`
   */
  
  AssertionError.prototype.toJSON = function (stack) {
    var extend = exclude('constructor', 'toJSON', 'stack')
      , props = extend({ name: this.name }, this);
  
    // include stack if exists and not turned off
    if (false !== stack && this.stack) {
      props.stack = this.stack;
    }
  
    return props;
  };
  
  },{}],8:[function(require,module,exports){
  module.exports = function _atob(str) {
    return atob(str)
  }
  
  },{}],9:[function(require,module,exports){
  var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  
  ;(function (exports) {
  	'use strict';
  
    var Arr = (typeof Uint8Array !== 'undefined')
      ? Uint8Array
      : Array
  
  	var PLUS   = '+'.charCodeAt(0)
  	var SLASH  = '/'.charCodeAt(0)
  	var NUMBER = '0'.charCodeAt(0)
  	var LOWER  = 'a'.charCodeAt(0)
  	var UPPER  = 'A'.charCodeAt(0)
  
  	function decode (elt) {
  		var code = elt.charCodeAt(0)
  		if (code === PLUS)
  			return 62 // '+'
  		if (code === SLASH)
  			return 63 // '/'
  		if (code < NUMBER)
  			return -1 //no match
  		if (code < NUMBER + 10)
  			return code - NUMBER + 26 + 26
  		if (code < UPPER + 26)
  			return code - UPPER
  		if (code < LOWER + 26)
  			return code - LOWER + 26
  	}
  
  	function b64ToByteArray (b64) {
  		var i, j, l, tmp, placeHolders, arr
  
  		if (b64.length % 4 > 0) {
  			throw new Error('Invalid string. Length must be a multiple of 4')
  		}
  
  		// the number of equal signs (place holders)
  		// if there are two placeholders, than the two characters before it
  		// represent one byte
  		// if there is only one, then the three characters before it represent 2 bytes
  		// this is just a cheap hack to not do indexOf twice
  		var len = b64.length
  		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
  
  		// base64 is 4/3 + up to two characters of the original data
  		arr = new Arr(b64.length * 3 / 4 - placeHolders)
  
  		// if there are placeholders, only get up to the last complete 4 chars
  		l = placeHolders > 0 ? b64.length - 4 : b64.length
  
  		var L = 0
  
  		function push (v) {
  			arr[L++] = v
  		}
  
  		for (i = 0, j = 0; i < l; i += 4, j += 3) {
  			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
  			push((tmp & 0xFF0000) >> 16)
  			push((tmp & 0xFF00) >> 8)
  			push(tmp & 0xFF)
  		}
  
  		if (placeHolders === 2) {
  			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
  			push(tmp & 0xFF)
  		} else if (placeHolders === 1) {
  			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
  			push((tmp >> 8) & 0xFF)
  			push(tmp & 0xFF)
  		}
  
  		return arr
  	}
  
  	function uint8ToBase64 (uint8) {
  		var i,
  			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
  			output = "",
  			temp, length
  
  		function encode (num) {
  			return lookup.charAt(num)
  		}
  
  		function tripletToBase64 (num) {
  			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
  		}
  
  		// go through the array every three bytes, we'll deal with trailing stuff later
  		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
  			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
  			output += tripletToBase64(temp)
  		}
  
  		// pad the end with zeros, but make sure to not forget the extra bytes
  		switch (extraBytes) {
  			case 1:
  				temp = uint8[uint8.length - 1]
  				output += encode(temp >> 2)
  				output += encode((temp << 4) & 0x3F)
  				output += '=='
  				break
  			case 2:
  				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
  				output += encode(temp >> 10)
  				output += encode((temp >> 4) & 0x3F)
  				output += encode((temp << 2) & 0x3F)
  				output += '='
  				break
  		}
  
  		return output
  	}
  
  	exports.toByteArray = b64ToByteArray
  	exports.fromByteArray = uint8ToBase64
  }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
  
  },{}],10:[function(require,module,exports){
  /**
   * Bit twiddling hacks for JavaScript.
   *
   * Author: Mikola Lysenko
   *
   * Ported from Stanford bit twiddling hack library:
   *    http://graphics.stanford.edu/~seander/bithacks.html
   */
  
  "use strict"; "use restrict";
  
  //Number of bits in an integer
  var INT_BITS = 32;
  
  //Constants
  exports.INT_BITS  = INT_BITS;
  exports.INT_MAX   =  0x7fffffff;
  exports.INT_MIN   = -1<<(INT_BITS-1);
  
  //Returns -1, 0, +1 depending on sign of x
  exports.sign = function(v) {
    return (v > 0) - (v < 0);
  }
  
  //Computes absolute value of integer
  exports.abs = function(v) {
    var mask = v >> (INT_BITS-1);
    return (v ^ mask) - mask;
  }
  
  //Computes minimum of integers x and y
  exports.min = function(x, y) {
    return y ^ ((x ^ y) & -(x < y));
  }
  
  //Computes maximum of integers x and y
  exports.max = function(x, y) {
    return x ^ ((x ^ y) & -(x < y));
  }
  
  //Checks if a number is a power of two
  exports.isPow2 = function(v) {
    return !(v & (v-1)) && (!!v);
  }
  
  //Computes log base 2 of v
  exports.log2 = function(v) {
    var r, shift;
    r =     (v > 0xFFFF) << 4; v >>>= r;
    shift = (v > 0xFF  ) << 3; v >>>= shift; r |= shift;
    shift = (v > 0xF   ) << 2; v >>>= shift; r |= shift;
    shift = (v > 0x3   ) << 1; v >>>= shift; r |= shift;
    return r | (v >> 1);
  }
  
  //Computes log base 10 of v
  exports.log10 = function(v) {
    return  (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
            (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
            (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
  }
  
  //Counts number of bits
  exports.popCount = function(v) {
    v = v - ((v >>> 1) & 0x55555555);
    v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);
    return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
  }
  
  //Counts number of trailing zeros
  function countTrailingZeros(v) {
    var c = 32;
    v &= -v;
    if (v) c--;
    if (v & 0x0000FFFF) c -= 16;
    if (v & 0x00FF00FF) c -= 8;
    if (v & 0x0F0F0F0F) c -= 4;
    if (v & 0x33333333) c -= 2;
    if (v & 0x55555555) c -= 1;
    return c;
  }
  exports.countTrailingZeros = countTrailingZeros;
  
  //Rounds to next power of 2
  exports.nextPow2 = function(v) {
    v += v === 0;
    --v;
    v |= v >>> 1;
    v |= v >>> 2;
    v |= v >>> 4;
    v |= v >>> 8;
    v |= v >>> 16;
    return v + 1;
  }
  
  //Rounds down to previous power of 2
  exports.prevPow2 = function(v) {
    v |= v >>> 1;
    v |= v >>> 2;
    v |= v >>> 4;
    v |= v >>> 8;
    v |= v >>> 16;
    return v - (v>>>1);
  }
  
  //Computes parity of word
  exports.parity = function(v) {
    v ^= v >>> 16;
    v ^= v >>> 8;
    v ^= v >>> 4;
    v &= 0xf;
    return (0x6996 >>> v) & 1;
  }
  
  var REVERSE_TABLE = new Array(256);
  
  (function(tab) {
    for(var i=0; i<256; ++i) {
      var v = i, r = i, s = 7;
      for (v >>>= 1; v; v >>>= 1) {
        r <<= 1;
        r |= v & 1;
        --s;
      }
      tab[i] = (r << s) & 0xff;
    }
  })(REVERSE_TABLE);
  
  //Reverse bits in a 32 bit word
  exports.reverse = function(v) {
    return  (REVERSE_TABLE[ v         & 0xff] << 24) |
            (REVERSE_TABLE[(v >>> 8)  & 0xff] << 16) |
            (REVERSE_TABLE[(v >>> 16) & 0xff] << 8)  |
             REVERSE_TABLE[(v >>> 24) & 0xff];
  }
  
  //Interleave bits of 2 coordinates with 16 bits.  Useful for fast quadtree codes
  exports.interleave2 = function(x, y) {
    x &= 0xFFFF;
    x = (x | (x << 8)) & 0x00FF00FF;
    x = (x | (x << 4)) & 0x0F0F0F0F;
    x = (x | (x << 2)) & 0x33333333;
    x = (x | (x << 1)) & 0x55555555;
  
    y &= 0xFFFF;
    y = (y | (y << 8)) & 0x00FF00FF;
    y = (y | (y << 4)) & 0x0F0F0F0F;
    y = (y | (y << 2)) & 0x33333333;
    y = (y | (y << 1)) & 0x55555555;
  
    return x | (y << 1);
  }
  
  //Extracts the nth interleaved component
  exports.deinterleave2 = function(v, n) {
    v = (v >>> n) & 0x55555555;
    v = (v | (v >>> 1))  & 0x33333333;
    v = (v | (v >>> 2))  & 0x0F0F0F0F;
    v = (v | (v >>> 4))  & 0x00FF00FF;
    v = (v | (v >>> 16)) & 0x000FFFF;
    return (v << 16) >> 16;
  }
  
  
  //Interleave bits of 3 coordinates, each with 10 bits.  Useful for fast octree codes
  exports.interleave3 = function(x, y, z) {
    x &= 0x3FF;
    x  = (x | (x<<16)) & 4278190335;
    x  = (x | (x<<8))  & 251719695;
    x  = (x | (x<<4))  & 3272356035;
    x  = (x | (x<<2))  & 1227133513;
  
    y &= 0x3FF;
    y  = (y | (y<<16)) & 4278190335;
    y  = (y | (y<<8))  & 251719695;
    y  = (y | (y<<4))  & 3272356035;
    y  = (y | (y<<2))  & 1227133513;
    x |= (y << 1);
    
    z &= 0x3FF;
    z  = (z | (z<<16)) & 4278190335;
    z  = (z | (z<<8))  & 251719695;
    z  = (z | (z<<4))  & 3272356035;
    z  = (z | (z<<2))  & 1227133513;
    
    return x | (z << 2);
  }
  
  //Extracts nth interleaved component of a 3-tuple
  exports.deinterleave3 = function(v, n) {
    v = (v >>> n)       & 1227133513;
    v = (v | (v>>>2))   & 3272356035;
    v = (v | (v>>>4))   & 251719695;
    v = (v | (v>>>8))   & 4278190335;
    v = (v | (v>>>16))  & 0x3FF;
    return (v<<22)>>22;
  }
  
  //Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page)
  exports.nextCombination = function(v) {
    var t = v | (v - 1);
    return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1));
  }
  
  
  },{}],11:[function(require,module,exports){
  // shim for using process in browser
  
  var process = module.exports = {};
  
  process.nextTick = (function () {
      var canSetImmediate = typeof window !== 'undefined'
      && window.setImmediate;
      var canMutationObserver = typeof window !== 'undefined'
      && window.MutationObserver;
      var canPost = typeof window !== 'undefined'
      && window.postMessage && window.addEventListener
      ;
  
      if (canSetImmediate) {
          return function (f) { return window.setImmediate(f) };
      }
  
      var queue = [];
  
      if (canMutationObserver) {
          var hiddenDiv = document.createElement("div");
          var observer = new MutationObserver(function () {
              var queueList = queue.slice();
              queue.length = 0;
              queueList.forEach(function (fn) {
                  fn();
              });
          });
  
          observer.observe(hiddenDiv, { attributes: true });
  
          return function nextTick(fn) {
              if (!queue.length) {
                  hiddenDiv.setAttribute('yes', 'no');
              }
              queue.push(fn);
          };
      }
  
      if (canPost) {
          window.addEventListener('message', function (ev) {
              var source = ev.source;
              if ((source === window || source === null) && ev.data === 'process-tick') {
                  ev.stopPropagation();
                  if (queue.length > 0) {
                      var fn = queue.shift();
                      fn();
                  }
              }
          }, true);
  
          return function nextTick(fn) {
              queue.push(fn);
              window.postMessage('process-tick', '*');
          };
      }
  
      return function nextTick(fn) {
          setTimeout(fn, 0);
      };
  })();
  
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  };
  
  // TODO(shtylman)
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  
  },{}],12:[function(require,module,exports){
  /*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  
  var base64 = require('base64-js')
  var ieee754 = require('ieee754')
  var isArray = require('is-array')
  
  exports.Buffer = Buffer
  exports.SlowBuffer = Buffer
  exports.INSPECT_MAX_BYTES = 50
  Buffer.poolSize = 8192 // not used by this implementation
  
  var kMaxLength = 0x3fffffff
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Use Object implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * Note:
   *
   * - Implementation must support adding new properties to `Uint8Array` instances.
   *   Firefox 4-29 lacked support, fixed in Firefox 30+.
   *   See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
   *
   *  - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
   *
   *  - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
   *    incorrect length in some situations.
   *
   * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will
   * get the Object implementation, which is slower but will work correctly.
   */
  Buffer.TYPED_ARRAY_SUPPORT = (function () {
    try {
      var buf = new ArrayBuffer(0)
      var arr = new Uint8Array(buf)
      arr.foo = function () { return 42 }
      return 42 === arr.foo() && // typed array instances can be augmented
          typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
          new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
    } catch (e) {
      return false
    }
  })()
  
  /**
   * Class: Buffer
   * =============
   *
   * The Buffer constructor returns instances of `Uint8Array` that are augmented
   * with function properties for all the node `Buffer` API functions. We use
   * `Uint8Array` so that square bracket notation works as expected -- it returns
   * a single octet.
   *
   * By augmenting the instances, we can avoid modifying the `Uint8Array`
   * prototype.
   */
  function Buffer (subject, encoding, noZero) {
    if (!(this instanceof Buffer))
      return new Buffer(subject, encoding, noZero)
  
    var type = typeof subject
  
    // Find the length
    var length
    if (type === 'number')
      length = subject > 0 ? subject >>> 0 : 0
    else if (type === 'string') {
      if (encoding === 'base64')
        subject = base64clean(subject)
      length = Buffer.byteLength(subject, encoding)
    } else if (type === 'object' && subject !== null) { // assume object is array-like
      if (subject.type === 'Buffer' && isArray(subject.data))
        subject = subject.data
      length = +subject.length > 0 ? Math.floor(+subject.length) : 0
    } else
      throw new TypeError('must start with number, buffer, array or string')
  
    if (this.length > kMaxLength)
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
        'size: 0x' + kMaxLength.toString(16) + ' bytes')
  
    var buf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Preferred: Return an augmented `Uint8Array` instance for best performance
      buf = Buffer._augment(new Uint8Array(length))
    } else {
      // Fallback: Return THIS instance of Buffer (created by `new`)
      buf = this
      buf.length = length
      buf._isBuffer = true
    }
  
    var i
    if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') {
      // Speed optimization -- use set if we're copying from a typed array
      buf._set(subject)
    } else if (isArrayish(subject)) {
      // Treat array-ish objects as a byte array
      if (Buffer.isBuffer(subject)) {
        for (i = 0; i < length; i++)
          buf[i] = subject.readUInt8(i)
      } else {
        for (i = 0; i < length; i++)
          buf[i] = ((subject[i] % 256) + 256) % 256
      }
    } else if (type === 'string') {
      buf.write(subject, 0, encoding)
    } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) {
      for (i = 0; i < length; i++) {
        buf[i] = 0
      }
    }
  
    return buf
  }
  
  Buffer.isBuffer = function (b) {
    return !!(b != null && b._isBuffer)
  }
  
  Buffer.compare = function (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b))
      throw new TypeError('Arguments must be Buffers')
  
    var x = a.length
    var y = b.length
    for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}
    if (i !== len) {
      x = a[i]
      y = b[i]
    }
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'binary':
      case 'base64':
      case 'raw':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function (list, totalLength) {
    if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])')
  
    if (list.length === 0) {
      return new Buffer(0)
    } else if (list.length === 1) {
      return list[0]
    }
  
    var i
    if (totalLength === undefined) {
      totalLength = 0
      for (i = 0; i < list.length; i++) {
        totalLength += list[i].length
      }
    }
  
    var buf = new Buffer(totalLength)
    var pos = 0
    for (i = 0; i < list.length; i++) {
      var item = list[i]
      item.copy(buf, pos)
      pos += item.length
    }
    return buf
  }
  
  Buffer.byteLength = function (str, encoding) {
    var ret
    str = str + ''
    switch (encoding || 'utf8') {
      case 'ascii':
      case 'binary':
      case 'raw':
        ret = str.length
        break
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        ret = str.length * 2
        break
      case 'hex':
        ret = str.length >>> 1
        break
      case 'utf8':
      case 'utf-8':
        ret = utf8ToBytes(str).length
        break
      case 'base64':
        ret = base64ToBytes(str).length
        break
      default:
        ret = str.length
    }
    return ret
  }
  
  // pre-set for values that may exist in the future
  Buffer.prototype.length = undefined
  Buffer.prototype.parent = undefined
  
  // toString(encoding, start=0, end=buffer.length)
  Buffer.prototype.toString = function (encoding, start, end) {
    var loweredCase = false
  
    start = start >>> 0
    end = end === undefined || end === Infinity ? this.length : end >>> 0
  
    if (!encoding) encoding = 'utf8'
    if (start < 0) start = 0
    if (end > this.length) end = this.length
    if (end <= start) return ''
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'binary':
          return binarySlice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase)
            throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.equals = function (b) {
    if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max)
        str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    return Buffer.compare(this, b)
  }
  
  // `get` will be removed in Node 0.13+
  Buffer.prototype.get = function (offset) {
    console.log('.get() is deprecated. Access using array indexes instead.')
    return this.readUInt8(offset)
  }
  
  // `set` will be removed in Node 0.13+
  Buffer.prototype.set = function (v, offset) {
    console.log('.set() is deprecated. Access using array indexes instead.')
    return this.writeUInt8(v, offset)
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new Error('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; i++) {
      var byte = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(byte)) throw new Error('Invalid hex string')
      buf[offset + i] = byte
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length)
    return charsWritten
  }
  
  function asciiWrite (buf, string, offset, length) {
    var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length)
    return charsWritten
  }
  
  function binaryWrite (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length)
    return charsWritten
  }
  
  function utf16leWrite (buf, string, offset, length) {
    var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length, 2)
    return charsWritten
  }
  
  Buffer.prototype.write = function (string, offset, length, encoding) {
    // Support both (string, offset, length, encoding)
    // and the legacy (string, encoding, offset, length)
    if (isFinite(offset)) {
      if (!isFinite(length)) {
        encoding = length
        length = undefined
      }
    } else {  // legacy
      var swap = encoding
      encoding = offset
      offset = length
      length = swap
    }
  
    offset = Number(offset) || 0
    var remaining = this.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
    encoding = String(encoding || 'utf8').toLowerCase()
  
    var ret
    switch (encoding) {
      case 'hex':
        ret = hexWrite(this, string, offset, length)
        break
      case 'utf8':
      case 'utf-8':
        ret = utf8Write(this, string, offset, length)
        break
      case 'ascii':
        ret = asciiWrite(this, string, offset, length)
        break
      case 'binary':
        ret = binaryWrite(this, string, offset, length)
        break
      case 'base64':
        ret = base64Write(this, string, offset, length)
        break
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        ret = utf16leWrite(this, string, offset, length)
        break
      default:
        throw new TypeError('Unknown encoding: ' + encoding)
    }
    return ret
  }
  
  Buffer.prototype.toJSON = function () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    var res = ''
    var tmp = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      if (buf[i] <= 0x7F) {
        res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
        tmp = ''
      } else {
        tmp += '%' + buf[i].toString(16)
      }
    }
  
    return res + decodeUtf8Char(tmp)
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function binarySlice (buf, start, end) {
    return asciiSlice(buf, start, end)
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.length
  
    if (!start || start < 0) start = 0
    if (!end || end < 0 || end > len) end = len
  
    var out = ''
    for (var i = start; i < end; i++) {
      out += toHex(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
    }
    return res
  }
  
  Buffer.prototype.slice = function (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len;
      if (start < 0)
        start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0)
        end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start)
      end = start
  
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      return Buffer._augment(this.subarray(start, end))
    } else {
      var sliceLen = end - start
      var newBuf = new Buffer(sliceLen, undefined, true)
      for (var i = 0; i < sliceLen; i++) {
        newBuf[i] = this[i + start]
      }
      return newBuf
    }
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0)
      throw new RangeError('offset is not uint')
    if (offset + ext > length)
      throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUInt8 = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
        ((this[offset + 1] << 16) |
        (this[offset + 2] << 8) |
        this[offset + 3])
  }
  
  Buffer.prototype.readInt8 = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80))
      return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16) |
        (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
        (this[offset + 1] << 16) |
        (this[offset + 2] << 8) |
        (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
    if (value > max || value < min) throw new TypeError('value is out of bounds')
    if (offset + ext > buf.length) throw new TypeError('index out of range')
  }
  
  Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 1, 0xff, 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    this[offset] = value
    return offset + 1
  }
  
  function objectWriteUInt16 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
      buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
        (littleEndian ? i : 1 - i) * 8
    }
  }
  
  Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
    } else objectWriteUInt16(this, value, offset, true)
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = value
    } else objectWriteUInt16(this, value, offset, false)
    return offset + 2
  }
  
  function objectWriteUInt32 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffffffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
      buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
    }
  }
  
  Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset + 3] = (value >>> 24)
      this[offset + 2] = (value >>> 16)
      this[offset + 1] = (value >>> 8)
      this[offset] = value
    } else objectWriteUInt32(this, value, offset, true)
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = value
    } else objectWriteUInt32(this, value, offset, false)
    return offset + 4
  }
  
  Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    if (value < 0) value = 0xff + value + 1
    this[offset] = value
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
    } else objectWriteUInt16(this, value, offset, true)
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = value
    } else objectWriteUInt16(this, value, offset, false)
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
      this[offset + 2] = (value >>> 16)
      this[offset + 3] = (value >>> 24)
    } else objectWriteUInt32(this, value, offset, true)
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = value
    } else objectWriteUInt32(this, value, offset, false)
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (value > max || value < min) throw new TypeError('value is out of bounds')
    if (offset + ext > buf.length) throw new TypeError('index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert)
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert)
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function (target, target_start, start, end) {
    var source = this
  
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (!target_start) target_start = 0
  
    // Copy 0 bytes; we're done
    if (end === start) return
    if (target.length === 0 || source.length === 0) return
  
    // Fatal error conditions
    if (end < start) throw new TypeError('sourceEnd < sourceStart')
    if (target_start < 0 || target_start >= target.length)
      throw new TypeError('targetStart out of bounds')
    if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds')
    if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length)
      end = this.length
    if (target.length - target_start < end - start)
      end = target.length - target_start + start
  
    var len = end - start
  
    if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
      for (var i = 0; i < len; i++) {
        target[i + target_start] = this[i + start]
      }
    } else {
      target._set(this.subarray(start, start + len), target_start)
    }
  }
  
  // fill(value, start=0, end=buffer.length)
  Buffer.prototype.fill = function (value, start, end) {
    if (!value) value = 0
    if (!start) start = 0
    if (!end) end = this.length
  
    if (end < start) throw new TypeError('end < start')
  
    // Fill 0 bytes; we're done
    if (end === start) return
    if (this.length === 0) return
  
    if (start < 0 || start >= this.length) throw new TypeError('start out of bounds')
    if (end < 0 || end > this.length) throw new TypeError('end out of bounds')
  
    var i
    if (typeof value === 'number') {
      for (i = start; i < end; i++) {
        this[i] = value
      }
    } else {
      var bytes = utf8ToBytes(value.toString())
      var len = bytes.length
      for (i = start; i < end; i++) {
        this[i] = bytes[i % len]
      }
    }
  
    return this
  }
  
  /**
   * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
   * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
   */
  Buffer.prototype.toArrayBuffer = function () {
    if (typeof Uint8Array !== 'undefined') {
      if (Buffer.TYPED_ARRAY_SUPPORT) {
        return (new Buffer(this)).buffer
      } else {
        var buf = new Uint8Array(this.length)
        for (var i = 0, len = buf.length; i < len; i += 1) {
          buf[i] = this[i]
        }
        return buf.buffer
      }
    } else {
      throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
    }
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var BP = Buffer.prototype
  
  /**
   * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
   */
  Buffer._augment = function (arr) {
    arr.constructor = Buffer
    arr._isBuffer = true
  
    // save reference to original Uint8Array get/set methods before overwriting
    arr._get = arr.get
    arr._set = arr.set
  
    // deprecated, will be removed in node 0.13+
    arr.get = BP.get
    arr.set = BP.set
  
    arr.write = BP.write
    arr.toString = BP.toString
    arr.toLocaleString = BP.toString
    arr.toJSON = BP.toJSON
    arr.equals = BP.equals
    arr.compare = BP.compare
    arr.copy = BP.copy
    arr.slice = BP.slice
    arr.readUInt8 = BP.readUInt8
    arr.readUInt16LE = BP.readUInt16LE
    arr.readUInt16BE = BP.readUInt16BE
    arr.readUInt32LE = BP.readUInt32LE
    arr.readUInt32BE = BP.readUInt32BE
    arr.readInt8 = BP.readInt8
    arr.readInt16LE = BP.readInt16LE
    arr.readInt16BE = BP.readInt16BE
    arr.readInt32LE = BP.readInt32LE
    arr.readInt32BE = BP.readInt32BE
    arr.readFloatLE = BP.readFloatLE
    arr.readFloatBE = BP.readFloatBE
    arr.readDoubleLE = BP.readDoubleLE
    arr.readDoubleBE = BP.readDoubleBE
    arr.writeUInt8 = BP.writeUInt8
    arr.writeUInt16LE = BP.writeUInt16LE
    arr.writeUInt16BE = BP.writeUInt16BE
    arr.writeUInt32LE = BP.writeUInt32LE
    arr.writeUInt32BE = BP.writeUInt32BE
    arr.writeInt8 = BP.writeInt8
    arr.writeInt16LE = BP.writeInt16LE
    arr.writeInt16BE = BP.writeInt16BE
    arr.writeInt32LE = BP.writeInt32LE
    arr.writeInt32BE = BP.writeInt32BE
    arr.writeFloatLE = BP.writeFloatLE
    arr.writeFloatBE = BP.writeFloatBE
    arr.writeDoubleLE = BP.writeDoubleLE
    arr.writeDoubleBE = BP.writeDoubleBE
    arr.fill = BP.fill
    arr.inspect = BP.inspect
    arr.toArrayBuffer = BP.toArrayBuffer
  
    return arr
  }
  
  var INVALID_BASE64_RE = /[^+\/0-9A-z]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function isArrayish (subject) {
    return isArray(subject) || Buffer.isBuffer(subject) ||
        subject && typeof subject === 'object' &&
        typeof subject.length === 'number'
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      var b = str.charCodeAt(i)
      if (b <= 0x7F) {
        byteArray.push(b)
      } else {
        var start = i
        if (b >= 0xD800 && b <= 0xDFFF) i++
        var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')
        for (var j = 0; j < h.length; j++) {
          byteArray.push(parseInt(h[j], 16))
        }
      }
    }
    return byteArray
  }
  
  function asciiToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  }
  
  function utf16leToBytes (str) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(str)
  }
  
  function blitBuffer (src, dst, offset, length, unitSize) {
    if (unitSize) length -= length % unitSize;
    for (var i = 0; i < length; i++) {
      if ((i + offset >= dst.length) || (i >= src.length))
        break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  function decodeUtf8Char (str) {
    try {
      return decodeURIComponent(str)
    } catch (err) {
      return String.fromCharCode(0xFFFD) // UTF 8 invalid char
    }
  }
  
  },{"base64-js":9,"ieee754":193,"is-array":196}],13:[function(require,module,exports){
  var size = require('element-size')
  
  module.exports = fit
  
  function fit(canvas, parent, scale) {
    canvas.style.position = canvas.style.position || 'absolute'
    canvas.style.top = 0
    canvas.style.left = 0
  
    scale = parseFloat(scale || 1)
  
    return resize()
  
    function resize() {
      var p = parent || canvas.parentNode
      if (p && p !== document.body) {
        var psize  = size(p)
        var width  = psize[0]|0
        var height = psize[1]|0
      } else {
        var width  = window.innerWidth
        var height = window.innerHeight
      }
  
      canvas.width = width * scale
      canvas.height = height * scale
      canvas.style.width = width + 'px'
      canvas.style.height = height + 'px'
  
      return resize
    }
  }
  
  },{"element-size":55}],14:[function(require,module,exports){
  module.exports = require('./lib/chai');
  
  },{"./lib/chai":15}],15:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var used = []
    , exports = module.exports = {};
  
  /*!
   * Chai version
   */
  
  exports.version = '3.4.1';
  
  /*!
   * Assertion Error
   */
  
  exports.AssertionError = require('assertion-error');
  
  /*!
   * Utils for plugins (not exported)
   */
  
  var util = require('./chai/utils');
  
  /**
   * # .use(function)
   *
   * Provides a way to extend the internals of Chai
   *
   * @param {Function}
   * @returns {this} for chaining
   * @api public
   */
  
  exports.use = function (fn) {
    if (!~used.indexOf(fn)) {
      fn(this, util);
      used.push(fn);
    }
  
    return this;
  };
  
  /*!
   * Utility Functions
   */
  
  exports.util = util;
  
  /*!
   * Configuration
   */
  
  var config = require('./chai/config');
  exports.config = config;
  
  /*!
   * Primary `Assertion` prototype
   */
  
  var assertion = require('./chai/assertion');
  exports.use(assertion);
  
  /*!
   * Core Assertions
   */
  
  var core = require('./chai/core/assertions');
  exports.use(core);
  
  /*!
   * Expect interface
   */
  
  var expect = require('./chai/interface/expect');
  exports.use(expect);
  
  /*!
   * Should interface
   */
  
  var should = require('./chai/interface/should');
  exports.use(should);
  
  /*!
   * Assert interface
   */
  
  var assert = require('./chai/interface/assert');
  exports.use(assert);
  
  },{"./chai/assertion":16,"./chai/config":17,"./chai/core/assertions":18,"./chai/interface/assert":19,"./chai/interface/expect":20,"./chai/interface/should":21,"./chai/utils":35,"assertion-error":7}],16:[function(require,module,exports){
  /*!
   * chai
   * http://chaijs.com
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var config = require('./config');
  
  module.exports = function (_chai, util) {
    /*!
     * Module dependencies.
     */
  
    var AssertionError = _chai.AssertionError
      , flag = util.flag;
  
    /*!
     * Module export.
     */
  
    _chai.Assertion = Assertion;
  
    /*!
     * Assertion Constructor
     *
     * Creates object for chaining.
     *
     * @api private
     */
  
    function Assertion (obj, msg, stack) {
      flag(this, 'ssfi', stack || arguments.callee);
      flag(this, 'object', obj);
      flag(this, 'message', msg);
    }
  
    Object.defineProperty(Assertion, 'includeStack', {
      get: function() {
        console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
        return config.includeStack;
      },
      set: function(value) {
        console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
        config.includeStack = value;
      }
    });
  
    Object.defineProperty(Assertion, 'showDiff', {
      get: function() {
        console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
        return config.showDiff;
      },
      set: function(value) {
        console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
        config.showDiff = value;
      }
    });
  
    Assertion.addProperty = function (name, fn) {
      util.addProperty(this.prototype, name, fn);
    };
  
    Assertion.addMethod = function (name, fn) {
      util.addMethod(this.prototype, name, fn);
    };
  
    Assertion.addChainableMethod = function (name, fn, chainingBehavior) {
      util.addChainableMethod(this.prototype, name, fn, chainingBehavior);
    };
  
    Assertion.overwriteProperty = function (name, fn) {
      util.overwriteProperty(this.prototype, name, fn);
    };
  
    Assertion.overwriteMethod = function (name, fn) {
      util.overwriteMethod(this.prototype, name, fn);
    };
  
    Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {
      util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
    };
  
    /**
     * ### .assert(expression, message, negateMessage, expected, actual, showDiff)
     *
     * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
     *
     * @name assert
     * @param {Philosophical} expression to be tested
     * @param {String|Function} message or function that returns message to display if expression fails
     * @param {String|Function} negatedMessage or function that returns negatedMessage to display if negated expression fails
     * @param {Mixed} expected value (remember to check for negation)
     * @param {Mixed} actual (optional) will default to `this.obj`
     * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails
     * @api private
     */
  
    Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
      var ok = util.test(this, arguments);
      if (true !== showDiff) showDiff = false;
      if (true !== config.showDiff) showDiff = false;
  
      if (!ok) {
        var msg = util.getMessage(this, arguments)
          , actual = util.getActual(this, arguments);
        throw new AssertionError(msg, {
            actual: actual
          , expected: expected
          , showDiff: showDiff
        }, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
      }
    };
  
    /*!
     * ### ._obj
     *
     * Quick reference to stored `actual` value for plugin developers.
     *
     * @api private
     */
  
    Object.defineProperty(Assertion.prototype, '_obj',
      { get: function () {
          return flag(this, 'object');
        }
      , set: function (val) {
          flag(this, 'object', val);
        }
    });
  };
  
  },{"./config":17}],17:[function(require,module,exports){
  module.exports = {
  
    /**
     * ### config.includeStack
     *
     * User configurable property, influences whether stack trace
     * is included in Assertion error message. Default of false
     * suppresses stack trace in the error message.
     *
     *     chai.config.includeStack = true;  // enable stack on error
     *
     * @param {Boolean}
     * @api public
     */
  
     includeStack: false,
  
    /**
     * ### config.showDiff
     *
     * User configurable property, influences whether or not
     * the `showDiff` flag should be included in the thrown
     * AssertionErrors. `false` will always be `false`; `true`
     * will be true when the assertion has requested a diff
     * be shown.
     *
     * @param {Boolean}
     * @api public
     */
  
    showDiff: true,
  
    /**
     * ### config.truncateThreshold
     *
     * User configurable property, sets length threshold for actual and
     * expected values in assertion errors. If this threshold is exceeded, for
     * example for large data structures, the value is replaced with something
     * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`.
     *
     * Set it to zero if you want to disable truncating altogether.
     *
     * This is especially userful when doing assertions on arrays: having this
     * set to a reasonable large value makes the failure messages readily
     * inspectable.
     *
     *     chai.config.truncateThreshold = 0;  // disable truncating
     *
     * @param {Number}
     * @api public
     */
  
    truncateThreshold: 40
  
  };
  
  },{}],18:[function(require,module,exports){
  /*!
   * chai
   * http://chaijs.com
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, _) {
    var Assertion = chai.Assertion
      , toString = Object.prototype.toString
      , flag = _.flag;
  
    /**
     * ### Language Chains
     *
     * The following are provided as chainable getters to
     * improve the readability of your assertions. They
     * do not provide testing capabilities unless they
     * have been overwritten by a plugin.
     *
     * **Chains**
     *
     * - to
     * - be
     * - been
     * - is
     * - that
     * - which
     * - and
     * - has
     * - have
     * - with
     * - at
     * - of
     * - same
     *
     * @name language chains
     * @api public
     */
  
    [ 'to', 'be', 'been'
    , 'is', 'and', 'has', 'have'
    , 'with', 'that', 'which', 'at'
    , 'of', 'same' ].forEach(function (chain) {
      Assertion.addProperty(chain, function () {
        return this;
      });
    });
  
    /**
     * ### .not
     *
     * Negates any of assertions following in the chain.
     *
     *     expect(foo).to.not.equal('bar');
     *     expect(goodFn).to.not.throw(Error);
     *     expect({ foo: 'baz' }).to.have.property('foo')
     *       .and.not.equal('bar');
     *
     * @name not
     * @api public
     */
  
    Assertion.addProperty('not', function () {
      flag(this, 'negate', true);
    });
  
    /**
     * ### .deep
     *
     * Sets the `deep` flag, later used by the `equal` and
     * `property` assertions.
     *
     *     expect(foo).to.deep.equal({ bar: 'baz' });
     *     expect({ foo: { bar: { baz: 'quux' } } })
     *       .to.have.deep.property('foo.bar.baz', 'quux');
     *
     * `.deep.property` special characters can be escaped
     * by adding two slashes before the `.` or `[]`.
     *
     *     var deepCss = { '.link': { '[target]': 42 }};
     *     expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
     *
     * @name deep
     * @api public
     */
  
    Assertion.addProperty('deep', function () {
      flag(this, 'deep', true);
    });
  
    /**
     * ### .any
     *
     * Sets the `any` flag, (opposite of the `all` flag)
     * later used in the `keys` assertion.
     *
     *     expect(foo).to.have.any.keys('bar', 'baz');
     *
     * @name any
     * @api public
     */
  
    Assertion.addProperty('any', function () {
      flag(this, 'any', true);
      flag(this, 'all', false)
    });
  
  
    /**
     * ### .all
     *
     * Sets the `all` flag (opposite of the `any` flag)
     * later used by the `keys` assertion.
     *
     *     expect(foo).to.have.all.keys('bar', 'baz');
     *
     * @name all
     * @api public
     */
  
    Assertion.addProperty('all', function () {
      flag(this, 'all', true);
      flag(this, 'any', false);
    });
  
    /**
     * ### .a(type)
     *
     * The `a` and `an` assertions are aliases that can be
     * used either as language chains or to assert a value's
     * type.
     *
     *     // typeof
     *     expect('test').to.be.a('string');
     *     expect({ foo: 'bar' }).to.be.an('object');
     *     expect(null).to.be.a('null');
     *     expect(undefined).to.be.an('undefined');
     *     expect(new Error).to.be.an('error');
     *     expect(new Promise).to.be.a('promise');
     *     expect(new Float32Array()).to.be.a('float32array');
     *     expect(Symbol()).to.be.a('symbol');
     *
     *     // es6 overrides
     *     expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo');
     *
     *     // language chain
     *     expect(foo).to.be.an.instanceof(Foo);
     *
     * @name a
     * @alias an
     * @param {String} type
     * @param {String} message _optional_
     * @api public
     */
  
    function an (type, msg) {
      if (msg) flag(this, 'message', msg);
      type = type.toLowerCase();
      var obj = flag(this, 'object')
        , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
  
      this.assert(
          type === _.type(obj)
        , 'expected #{this} to be ' + article + type
        , 'expected #{this} not to be ' + article + type
      );
    }
  
    Assertion.addChainableMethod('an', an);
    Assertion.addChainableMethod('a', an);
  
    /**
     * ### .include(value)
     *
     * The `include` and `contain` assertions can be used as either property
     * based language chains or as methods to assert the inclusion of an object
     * in an array or a substring in a string. When used as language chains,
     * they toggle the `contains` flag for the `keys` assertion.
     *
     *     expect([1,2,3]).to.include(2);
     *     expect('foobar').to.contain('foo');
     *     expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
     *
     * @name include
     * @alias contain
     * @alias includes
     * @alias contains
     * @param {Object|String|Number} obj
     * @param {String} message _optional_
     * @api public
     */
  
    function includeChainingBehavior () {
      flag(this, 'contains', true);
    }
  
    function include (val, msg) {
      _.expectTypes(this, ['array', 'object', 'string']);
  
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var expected = false;
  
      if (_.type(obj) === 'array' && _.type(val) === 'object') {
        for (var i in obj) {
          if (_.eql(obj[i], val)) {
            expected = true;
            break;
          }
        }
      } else if (_.type(val) === 'object') {
        if (!flag(this, 'negate')) {
          for (var k in val) new Assertion(obj).property(k, val[k]);
          return;
        }
        var subset = {};
        for (var k in val) subset[k] = obj[k];
        expected = _.eql(subset, val);
      } else {
        expected = (obj != undefined) && ~obj.indexOf(val);
      }
      this.assert(
          expected
        , 'expected #{this} to include ' + _.inspect(val)
        , 'expected #{this} to not include ' + _.inspect(val));
    }
  
    Assertion.addChainableMethod('include', include, includeChainingBehavior);
    Assertion.addChainableMethod('contain', include, includeChainingBehavior);
    Assertion.addChainableMethod('contains', include, includeChainingBehavior);
    Assertion.addChainableMethod('includes', include, includeChainingBehavior);
  
    /**
     * ### .ok
     *
     * Asserts that the target is truthy.
     *
     *     expect('everything').to.be.ok;
     *     expect(1).to.be.ok;
     *     expect(false).to.not.be.ok;
     *     expect(undefined).to.not.be.ok;
     *     expect(null).to.not.be.ok;
     *
     * @name ok
     * @api public
     */
  
    Assertion.addProperty('ok', function () {
      this.assert(
          flag(this, 'object')
        , 'expected #{this} to be truthy'
        , 'expected #{this} to be falsy');
    });
  
    /**
     * ### .true
     *
     * Asserts that the target is `true`.
     *
     *     expect(true).to.be.true;
     *     expect(1).to.not.be.true;
     *
     * @name true
     * @api public
     */
  
    Assertion.addProperty('true', function () {
      this.assert(
          true === flag(this, 'object')
        , 'expected #{this} to be true'
        , 'expected #{this} to be false'
        , this.negate ? false : true
      );
    });
  
    /**
     * ### .false
     *
     * Asserts that the target is `false`.
     *
     *     expect(false).to.be.false;
     *     expect(0).to.not.be.false;
     *
     * @name false
     * @api public
     */
  
    Assertion.addProperty('false', function () {
      this.assert(
          false === flag(this, 'object')
        , 'expected #{this} to be false'
        , 'expected #{this} to be true'
        , this.negate ? true : false
      );
    });
  
    /**
     * ### .null
     *
     * Asserts that the target is `null`.
     *
     *     expect(null).to.be.null;
     *     expect(undefined).to.not.be.null;
     *
     * @name null
     * @api public
     */
  
    Assertion.addProperty('null', function () {
      this.assert(
          null === flag(this, 'object')
        , 'expected #{this} to be null'
        , 'expected #{this} not to be null'
      );
    });
  
    /**
     * ### .undefined
     *
     * Asserts that the target is `undefined`.
     *
     *     expect(undefined).to.be.undefined;
     *     expect(null).to.not.be.undefined;
     *
     * @name undefined
     * @api public
     */
  
    Assertion.addProperty('undefined', function () {
      this.assert(
          undefined === flag(this, 'object')
        , 'expected #{this} to be undefined'
        , 'expected #{this} not to be undefined'
      );
    });
  
    /**
     * ### .NaN
     * Asserts that the target is `NaN`.
     *
     *     expect('foo').to.be.NaN;
     *     expect(4).not.to.be.NaN;
     *
     * @name NaN
     * @api public
     */
  
    Assertion.addProperty('NaN', function () {
      this.assert(
          isNaN(flag(this, 'object'))
          , 'expected #{this} to be NaN'
          , 'expected #{this} not to be NaN'
      );
    });
  
    /**
     * ### .exist
     *
     * Asserts that the target is neither `null` nor `undefined`.
     *
     *     var foo = 'hi'
     *       , bar = null
     *       , baz;
     *
     *     expect(foo).to.exist;
     *     expect(bar).to.not.exist;
     *     expect(baz).to.not.exist;
     *
     * @name exist
     * @api public
     */
  
    Assertion.addProperty('exist', function () {
      this.assert(
          null != flag(this, 'object')
        , 'expected #{this} to exist'
        , 'expected #{this} to not exist'
      );
    });
  
  
    /**
     * ### .empty
     *
     * Asserts that the target's length is `0`. For arrays and strings, it checks
     * the `length` property. For objects, it gets the count of
     * enumerable keys.
     *
     *     expect([]).to.be.empty;
     *     expect('').to.be.empty;
     *     expect({}).to.be.empty;
     *
     * @name empty
     * @api public
     */
  
    Assertion.addProperty('empty', function () {
      var obj = flag(this, 'object')
        , expected = obj;
  
      if (Array.isArray(obj) || 'string' === typeof object) {
        expected = obj.length;
      } else if (typeof obj === 'object') {
        expected = Object.keys(obj).length;
      }
  
      this.assert(
          !expected
        , 'expected #{this} to be empty'
        , 'expected #{this} not to be empty'
      );
    });
  
    /**
     * ### .arguments
     *
     * Asserts that the target is an arguments object.
     *
     *     function test () {
     *       expect(arguments).to.be.arguments;
     *     }
     *
     * @name arguments
     * @alias Arguments
     * @api public
     */
  
    function checkArguments () {
      var obj = flag(this, 'object')
        , type = Object.prototype.toString.call(obj);
      this.assert(
          '[object Arguments]' === type
        , 'expected #{this} to be arguments but got ' + type
        , 'expected #{this} to not be arguments'
      );
    }
  
    Assertion.addProperty('arguments', checkArguments);
    Assertion.addProperty('Arguments', checkArguments);
  
    /**
     * ### .equal(value)
     *
     * Asserts that the target is strictly equal (`===`) to `value`.
     * Alternately, if the `deep` flag is set, asserts that
     * the target is deeply equal to `value`.
     *
     *     expect('hello').to.equal('hello');
     *     expect(42).to.equal(42);
     *     expect(1).to.not.equal(true);
     *     expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
     *     expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
     *
     * @name equal
     * @alias equals
     * @alias eq
     * @alias deep.equal
     * @param {Mixed} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertEqual (val, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'deep')) {
        return this.eql(val);
      } else {
        this.assert(
            val === obj
          , 'expected #{this} to equal #{exp}'
          , 'expected #{this} to not equal #{exp}'
          , val
          , this._obj
          , true
        );
      }
    }
  
    Assertion.addMethod('equal', assertEqual);
    Assertion.addMethod('equals', assertEqual);
    Assertion.addMethod('eq', assertEqual);
  
    /**
     * ### .eql(value)
     *
     * Asserts that the target is deeply equal to `value`.
     *
     *     expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
     *     expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
     *
     * @name eql
     * @alias eqls
     * @param {Mixed} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertEql(obj, msg) {
      if (msg) flag(this, 'message', msg);
      this.assert(
          _.eql(obj, flag(this, 'object'))
        , 'expected #{this} to deeply equal #{exp}'
        , 'expected #{this} to not deeply equal #{exp}'
        , obj
        , this._obj
        , true
      );
    }
  
    Assertion.addMethod('eql', assertEql);
    Assertion.addMethod('eqls', assertEql);
  
    /**
     * ### .above(value)
     *
     * Asserts that the target is greater than `value`.
     *
     *     expect(10).to.be.above(5);
     *
     * Can also be used in conjunction with `length` to
     * assert a minimum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.above(2);
     *     expect([ 1, 2, 3 ]).to.have.length.above(2);
     *
     * @name above
     * @alias gt
     * @alias greaterThan
     * @param {Number} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertAbove (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len > n
          , 'expected #{this} to have a length above #{exp} but got #{act}'
          , 'expected #{this} to not have a length above #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj > n
          , 'expected #{this} to be above ' + n
          , 'expected #{this} to be at most ' + n
        );
      }
    }
  
    Assertion.addMethod('above', assertAbove);
    Assertion.addMethod('gt', assertAbove);
    Assertion.addMethod('greaterThan', assertAbove);
  
    /**
     * ### .least(value)
     *
     * Asserts that the target is greater than or equal to `value`.
     *
     *     expect(10).to.be.at.least(10);
     *
     * Can also be used in conjunction with `length` to
     * assert a minimum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.of.at.least(2);
     *     expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
     *
     * @name least
     * @alias gte
     * @param {Number} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertLeast (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len >= n
          , 'expected #{this} to have a length at least #{exp} but got #{act}'
          , 'expected #{this} to have a length below #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj >= n
          , 'expected #{this} to be at least ' + n
          , 'expected #{this} to be below ' + n
        );
      }
    }
  
    Assertion.addMethod('least', assertLeast);
    Assertion.addMethod('gte', assertLeast);
  
    /**
     * ### .below(value)
     *
     * Asserts that the target is less than `value`.
     *
     *     expect(5).to.be.below(10);
     *
     * Can also be used in conjunction with `length` to
     * assert a maximum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.below(4);
     *     expect([ 1, 2, 3 ]).to.have.length.below(4);
     *
     * @name below
     * @alias lt
     * @alias lessThan
     * @param {Number} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertBelow (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len < n
          , 'expected #{this} to have a length below #{exp} but got #{act}'
          , 'expected #{this} to not have a length below #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj < n
          , 'expected #{this} to be below ' + n
          , 'expected #{this} to be at least ' + n
        );
      }
    }
  
    Assertion.addMethod('below', assertBelow);
    Assertion.addMethod('lt', assertBelow);
    Assertion.addMethod('lessThan', assertBelow);
  
    /**
     * ### .most(value)
     *
     * Asserts that the target is less than or equal to `value`.
     *
     *     expect(5).to.be.at.most(5);
     *
     * Can also be used in conjunction with `length` to
     * assert a maximum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.of.at.most(4);
     *     expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
     *
     * @name most
     * @alias lte
     * @param {Number} value
     * @param {String} message _optional_
     * @api public
     */
  
    function assertMost (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len <= n
          , 'expected #{this} to have a length at most #{exp} but got #{act}'
          , 'expected #{this} to have a length above #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj <= n
          , 'expected #{this} to be at most ' + n
          , 'expected #{this} to be above ' + n
        );
      }
    }
  
    Assertion.addMethod('most', assertMost);
    Assertion.addMethod('lte', assertMost);
  
    /**
     * ### .within(start, finish)
     *
     * Asserts that the target is within a range.
     *
     *     expect(7).to.be.within(5,10);
     *
     * Can also be used in conjunction with `length` to
     * assert a length range. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.within(2,4);
     *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);
     *
     * @name within
     * @param {Number} start lowerbound inclusive
     * @param {Number} finish upperbound inclusive
     * @param {String} message _optional_
     * @api public
     */
  
    Assertion.addMethod('within', function (start, finish, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object')
        , range = start + '..' + finish;
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len >= start && len <= finish
          , 'expected #{this} to have a length within ' + range
          , 'expected #{this} to not have a length within ' + range
        );
      } else {
        this.assert(
            obj >= start && obj <= finish
          , 'expected #{this} to be within ' + range
          , 'expected #{this} to not be within ' + range
        );
      }
    });
  
    /**
     * ### .instanceof(constructor)
     *
     * Asserts that the target is an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , Chai = new Tea('chai');
     *
     *     expect(Chai).to.be.an.instanceof(Tea);
     *     expect([ 1, 2, 3 ]).to.be.instanceof(Array);
     *
     * @name instanceof
     * @param {Constructor} constructor
     * @param {String} message _optional_
     * @alias instanceOf
     * @api public
     */
  
    function assertInstanceOf (constructor, msg) {
      if (msg) flag(this, 'message', msg);
      var name = _.getName(constructor);
      this.assert(
          flag(this, 'object') instanceof constructor
        , 'expected #{this} to be an instance of ' + name
        , 'expected #{this} to not be an instance of ' + name
      );
    };
  
    Assertion.addMethod('instanceof', assertInstanceOf);
    Assertion.addMethod('instanceOf', assertInstanceOf);
  
    /**
     * ### .property(name, [value])
     *
     * Asserts that the target has a property `name`, optionally asserting that
     * the value of that property is strictly equal to  `value`.
     * If the `deep` flag is set, you can use dot- and bracket-notation for deep
     * references into objects and arrays.
     *
     *     // simple referencing
     *     var obj = { foo: 'bar' };
     *     expect(obj).to.have.property('foo');
     *     expect(obj).to.have.property('foo', 'bar');
     *
     *     // deep referencing
     *     var deepObj = {
     *         green: { tea: 'matcha' }
     *       , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
     *     };
     *
     *     expect(deepObj).to.have.deep.property('green.tea', 'matcha');
     *     expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
     *     expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
     *
     * You can also use an array as the starting point of a `deep.property`
     * assertion, or traverse nested arrays.
     *
     *     var arr = [
     *         [ 'chai', 'matcha', 'konacha' ]
     *       , [ { tea: 'chai' }
     *         , { tea: 'matcha' }
     *         , { tea: 'konacha' } ]
     *     ];
     *
     *     expect(arr).to.have.deep.property('[0][1]', 'matcha');
     *     expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
     *
     * Furthermore, `property` changes the subject of the assertion
     * to be the value of that property from the original object. This
     * permits for further chainable assertions on that property.
     *
     *     expect(obj).to.have.property('foo')
     *       .that.is.a('string');
     *     expect(deepObj).to.have.property('green')
     *       .that.is.an('object')
     *       .that.deep.equals({ tea: 'matcha' });
     *     expect(deepObj).to.have.property('teas')
     *       .that.is.an('array')
     *       .with.deep.property('[2]')
     *         .that.deep.equals({ tea: 'konacha' });
     *
     * Note that dots and bracket in `name` must be backslash-escaped when
     * the `deep` flag is set, while they must NOT be escaped when the `deep`
     * flag is not set.
     *
     *     // simple referencing
     *     var css = { '.link[target]': 42 };
     *     expect(css).to.have.property('.link[target]', 42);
     *
     *     // deep referencing
     *     var deepCss = { '.link': { '[target]': 42 }};
     *     expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
     *
     * @name property
     * @alias deep.property
     * @param {String} name
     * @param {Mixed} value (optional)
     * @param {String} message _optional_
     * @returns value of property for chaining
     * @api public
     */
  
    Assertion.addMethod('property', function (name, val, msg) {
      if (msg) flag(this, 'message', msg);
  
      var isDeep = !!flag(this, 'deep')
        , descriptor = isDeep ? 'deep property ' : 'property '
        , negate = flag(this, 'negate')
        , obj = flag(this, 'object')
        , pathInfo = isDeep ? _.getPathInfo(name, obj) : null
        , hasProperty = isDeep
          ? pathInfo.exists
          : _.hasProperty(name, obj)
        , value = isDeep
          ? pathInfo.value
          : obj[name];
  
      if (negate && arguments.length > 1) {
        if (undefined === value) {
          msg = (msg != null) ? msg + ': ' : '';
          throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
        }
      } else {
        this.assert(
            hasProperty
          , 'expected #{this} to have a ' + descriptor + _.inspect(name)
          , 'expected #{this} to not have ' + descriptor + _.inspect(name));
      }
  
      if (arguments.length > 1) {
        this.assert(
            val === value
          , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
          , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
          , val
          , value
        );
      }
  
      flag(this, 'object', value);
    });
  
  
    /**
     * ### .ownProperty(name)
     *
     * Asserts that the target has an own property `name`.
     *
     *     expect('test').to.have.ownProperty('length');
     *
     * @name ownProperty
     * @alias haveOwnProperty
     * @param {String} name
     * @param {String} message _optional_
     * @api public
     */
  
    function assertOwnProperty (name, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      this.assert(
          obj.hasOwnProperty(name)
        , 'expected #{this} to have own property ' + _.inspect(name)
        , 'expected #{this} to not have own property ' + _.inspect(name)
      );
    }
  
    Assertion.addMethod('ownProperty', assertOwnProperty);
    Assertion.addMethod('haveOwnProperty', assertOwnProperty);
  
    /**
     * ### .ownPropertyDescriptor(name[, descriptor[, message]])
     *
     * Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`.
     *
     *     expect('test').to.have.ownPropertyDescriptor('length');
     *     expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 });
     *     expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 });
     *     expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false);
     *     expect('test').ownPropertyDescriptor('length').to.have.keys('value');
     *
     * @name ownPropertyDescriptor
     * @alias haveOwnPropertyDescriptor
     * @param {String} name
     * @param {Object} descriptor _optional_
     * @param {String} message _optional_
     * @api public
     */
  
    function assertOwnPropertyDescriptor (name, descriptor, msg) {
      if (typeof descriptor === 'string') {
        msg = descriptor;
        descriptor = null;
      }
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
      if (actualDescriptor && descriptor) {
        this.assert(
            _.eql(descriptor, actualDescriptor)
          , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)
          , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)
          , descriptor
          , actualDescriptor
          , true
        );
      } else {
        this.assert(
            actualDescriptor
          , 'expected #{this} to have an own property descriptor for ' + _.inspect(name)
          , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name)
        );
      }
      flag(this, 'object', actualDescriptor);
    }
  
    Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
    Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
  
    /**
     * ### .length
     *
     * Sets the `doLength` flag later used as a chain precursor to a value
     * comparison for the `length` property.
     *
     *     expect('foo').to.have.length.above(2);
     *     expect([ 1, 2, 3 ]).to.have.length.above(2);
     *     expect('foo').to.have.length.below(4);
     *     expect([ 1, 2, 3 ]).to.have.length.below(4);
     *     expect('foo').to.have.length.within(2,4);
     *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);
     *
     * *Deprecation notice:* Using `length` as an assertion will be deprecated
     * in version 2.4.0 and removed in 3.0.0. Code using the old style of
     * asserting for `length` property value using `length(value)` should be
     * switched to use `lengthOf(value)` instead.
     *
     * @name length
     * @api public
     */
  
    /**
     * ### .lengthOf(value[, message])
     *
     * Asserts that the target's `length` property has
     * the expected value.
     *
     *     expect([ 1, 2, 3]).to.have.lengthOf(3);
     *     expect('foobar').to.have.lengthOf(6);
     *
     * @name lengthOf
     * @param {Number} length
     * @param {String} message _optional_
     * @api public
     */
  
    function assertLengthChain () {
      flag(this, 'doLength', true);
    }
  
    function assertLength (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).to.have.property('length');
      var len = obj.length;
  
      this.assert(
          len == n
        , 'expected #{this} to have a length of #{exp} but got #{act}'
        , 'expected #{this} to not have a length of #{act}'
        , n
        , len
      );
    }
  
    Assertion.addChainableMethod('length', assertLength, assertLengthChain);
    Assertion.addMethod('lengthOf', assertLength);
  
    /**
     * ### .match(regexp)
     *
     * Asserts that the target matches a regular expression.
     *
     *     expect('foobar').to.match(/^foo/);
     *
     * @name match
     * @alias matches
     * @param {RegExp} RegularExpression
     * @param {String} message _optional_
     * @api public
     */
    function assertMatch(re, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      this.assert(
          re.exec(obj)
        , 'expected #{this} to match ' + re
        , 'expected #{this} not to match ' + re
      );
    }
  
    Assertion.addMethod('match', assertMatch);
    Assertion.addMethod('matches', assertMatch);
  
    /**
     * ### .string(string)
     *
     * Asserts that the string target contains another string.
     *
     *     expect('foobar').to.have.string('bar');
     *
     * @name string
     * @param {String} string
     * @param {String} message _optional_
     * @api public
     */
  
    Assertion.addMethod('string', function (str, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).is.a('string');
  
      this.assert(
          ~obj.indexOf(str)
        , 'expected #{this} to contain ' + _.inspect(str)
        , 'expected #{this} to not contain ' + _.inspect(str)
      );
    });
  
  
    /**
     * ### .keys(key1, [key2], [...])
     *
     * Asserts that the target contains any or all of the passed-in keys.
     * Use in combination with `any`, `all`, `contains`, or `have` will affect
     * what will pass.
     *
     * When used in conjunction with `any`, at least one key that is passed
     * in must exist in the target object. This is regardless whether or not
     * the `have` or `contain` qualifiers are used. Note, either `any` or `all`
     * should be used in the assertion. If neither are used, the assertion is
     * defaulted to `all`.
     *
     * When both `all` and `contain` are used, the target object must have at
     * least all of the passed-in keys but may have more keys not listed.
     *
     * When both `all` and `have` are used, the target object must both contain
     * all of the passed-in keys AND the number of keys in the target object must
     * match the number of keys passed in (in other words, a target object must
     * have all and only all of the passed-in keys).
     *
     *     expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz');
     *     expect({ foo: 1, bar: 2 }).to.have.any.keys('foo');
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz');
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']);
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6});
     *     expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']);
     *     expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7});
     *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']);
     *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys({'bar': 6});
     *
     *
     * @name keys
     * @alias key
     * @param {...String|Array|Object} keys
     * @api public
     */
  
    function assertKeys (keys) {
      var obj = flag(this, 'object')
        , str
        , ok = true
        , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments';
  
      switch (_.type(keys)) {
        case "array":
          if (arguments.length > 1) throw (new Error(mixedArgsMsg));
          break;
        case "object":
          if (arguments.length > 1) throw (new Error(mixedArgsMsg));
          keys = Object.keys(keys);
          break;
        default:
          keys = Array.prototype.slice.call(arguments);
      }
  
      if (!keys.length) throw new Error('keys required');
  
      var actual = Object.keys(obj)
        , expected = keys
        , len = keys.length
        , any = flag(this, 'any')
        , all = flag(this, 'all');
  
      if (!any && !all) {
        all = true;
      }
  
      // Has any
      if (any) {
        var intersection = expected.filter(function(key) {
          return ~actual.indexOf(key);
        });
        ok = intersection.length > 0;
      }
  
      // Has all
      if (all) {
        ok = keys.every(function(key){
          return ~actual.indexOf(key);
        });
        if (!flag(this, 'negate') && !flag(this, 'contains')) {
          ok = ok && keys.length == actual.length;
        }
      }
  
      // Key string
      if (len > 1) {
        keys = keys.map(function(key){
          return _.inspect(key);
        });
        var last = keys.pop();
        if (all) {
          str = keys.join(', ') + ', and ' + last;
        }
        if (any) {
          str = keys.join(', ') + ', or ' + last;
        }
      } else {
        str = _.inspect(keys[0]);
      }
  
      // Form
      str = (len > 1 ? 'keys ' : 'key ') + str;
  
      // Have / include
      str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
  
      // Assertion
      this.assert(
          ok
        , 'expected #{this} to ' + str
        , 'expected #{this} to not ' + str
        , expected.slice(0).sort()
        , actual.sort()
        , true
      );
    }
  
    Assertion.addMethod('keys', assertKeys);
    Assertion.addMethod('key', assertKeys);
  
    /**
     * ### .throw(constructor)
     *
     * Asserts that the function target will throw a specific error, or specific type of error
     * (as determined using `instanceof`), optionally with a RegExp or string inclusion test
     * for the error's message.
     *
     *     var err = new ReferenceError('This is a bad function.');
     *     var fn = function () { throw err; }
     *     expect(fn).to.throw(ReferenceError);
     *     expect(fn).to.throw(Error);
     *     expect(fn).to.throw(/bad function/);
     *     expect(fn).to.not.throw('good function');
     *     expect(fn).to.throw(ReferenceError, /bad function/);
     *     expect(fn).to.throw(err);
     *
     * Please note that when a throw expectation is negated, it will check each
     * parameter independently, starting with error constructor type. The appropriate way
     * to check for the existence of a type of error but for a message that does not match
     * is to use `and`.
     *
     *     expect(fn).to.throw(ReferenceError)
     *        .and.not.throw(/good function/);
     *
     * @name throw
     * @alias throws
     * @alias Throw
     * @param {ErrorConstructor} constructor
     * @param {String|RegExp} expected error message
     * @param {String} message _optional_
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @returns error for chaining (null if no error)
     * @api public
     */
  
    function assertThrows (constructor, errMsg, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).is.a('function');
  
      var thrown = false
        , desiredError = null
        , name = null
        , thrownError = null;
  
      if (arguments.length === 0) {
        errMsg = null;
        constructor = null;
      } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
        errMsg = constructor;
        constructor = null;
      } else if (constructor && constructor instanceof Error) {
        desiredError = constructor;
        constructor = null;
        errMsg = null;
      } else if (typeof constructor === 'function') {
        name = constructor.prototype.name;
        if (!name || (name === 'Error' && constructor !== Error)) {
          name = constructor.name || (new constructor()).name;
        }
      } else {
        constructor = null;
      }
  
      try {
        obj();
      } catch (err) {
        // first, check desired error
        if (desiredError) {
          this.assert(
              err === desiredError
            , 'expected #{this} to throw #{exp} but #{act} was thrown'
            , 'expected #{this} to not throw #{exp}'
            , (desiredError instanceof Error ? desiredError.toString() : desiredError)
            , (err instanceof Error ? err.toString() : err)
          );
  
          flag(this, 'object', err);
          return this;
        }
  
        // next, check constructor
        if (constructor) {
          this.assert(
              err instanceof constructor
            , 'expected #{this} to throw #{exp} but #{act} was thrown'
            , 'expected #{this} to not throw #{exp} but #{act} was thrown'
            , name
            , (err instanceof Error ? err.toString() : err)
          );
  
          if (!errMsg) {
            flag(this, 'object', err);
            return this;
          }
        }
  
        // next, check message
        var message = 'error' === _.type(err) && "message" in err
          ? err.message
          : '' + err;
  
        if ((message != null) && errMsg && errMsg instanceof RegExp) {
          this.assert(
              errMsg.exec(message)
            , 'expected #{this} to throw error matching #{exp} but got #{act}'
            , 'expected #{this} to throw error not matching #{exp}'
            , errMsg
            , message
          );
  
          flag(this, 'object', err);
          return this;
        } else if ((message != null) && errMsg && 'string' === typeof errMsg) {
          this.assert(
              ~message.indexOf(errMsg)
            , 'expected #{this} to throw error including #{exp} but got #{act}'
            , 'expected #{this} to throw error not including #{act}'
            , errMsg
            , message
          );
  
          flag(this, 'object', err);
          return this;
        } else {
          thrown = true;
          thrownError = err;
        }
      }
  
      var actuallyGot = ''
        , expectedThrown = name !== null
          ? name
          : desiredError
            ? '#{exp}' //_.inspect(desiredError)
            : 'an error';
  
      if (thrown) {
        actuallyGot = ' but #{act} was thrown'
      }
  
      this.assert(
          thrown === true
        , 'expected #{this} to throw ' + expectedThrown + actuallyGot
        , 'expected #{this} to not throw ' + expectedThrown + actuallyGot
        , (desiredError instanceof Error ? desiredError.toString() : desiredError)
        , (thrownError instanceof Error ? thrownError.toString() : thrownError)
      );
  
      flag(this, 'object', thrownError);
    };
  
    Assertion.addMethod('throw', assertThrows);
    Assertion.addMethod('throws', assertThrows);
    Assertion.addMethod('Throw', assertThrows);
  
    /**
     * ### .respondTo(method)
     *
     * Asserts that the object or class target will respond to a method.
     *
     *     Klass.prototype.bar = function(){};
     *     expect(Klass).to.respondTo('bar');
     *     expect(obj).to.respondTo('bar');
     *
     * To check if a constructor will respond to a static function,
     * set the `itself` flag.
     *
     *     Klass.baz = function(){};
     *     expect(Klass).itself.to.respondTo('baz');
     *
     * @name respondTo
     * @alias respondsTo
     * @param {String} method
     * @param {String} message _optional_
     * @api public
     */
  
    function respondTo (method, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object')
        , itself = flag(this, 'itself')
        , context = ('function' === _.type(obj) && !itself)
          ? obj.prototype[method]
          : obj[method];
  
      this.assert(
          'function' === typeof context
        , 'expected #{this} to respond to ' + _.inspect(method)
        , 'expected #{this} to not respond to ' + _.inspect(method)
      );
    }
  
    Assertion.addMethod('respondTo', respondTo);
    Assertion.addMethod('respondsTo', respondTo);
  
    /**
     * ### .itself
     *
     * Sets the `itself` flag, later used by the `respondTo` assertion.
     *
     *     function Foo() {}
     *     Foo.bar = function() {}
     *     Foo.prototype.baz = function() {}
     *
     *     expect(Foo).itself.to.respondTo('bar');
     *     expect(Foo).itself.not.to.respondTo('baz');
     *
     * @name itself
     * @api public
     */
  
    Assertion.addProperty('itself', function () {
      flag(this, 'itself', true);
    });
  
    /**
     * ### .satisfy(method)
     *
     * Asserts that the target passes a given truth test.
     *
     *     expect(1).to.satisfy(function(num) { return num > 0; });
     *
     * @name satisfy
     * @alias satisfies
     * @param {Function} matcher
     * @param {String} message _optional_
     * @api public
     */
  
    function satisfy (matcher, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var result = matcher(obj);
      this.assert(
          result
        , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
        , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
        , this.negate ? false : true
        , result
      );
    }
  
    Assertion.addMethod('satisfy', satisfy);
    Assertion.addMethod('satisfies', satisfy);
  
    /**
     * ### .closeTo(expected, delta)
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     expect(1.5).to.be.closeTo(1, 0.5);
     *
     * @name closeTo
     * @alias approximately
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message _optional_
     * @api public
     */
  
    function closeTo(expected, delta, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
  
      new Assertion(obj, msg).is.a('number');
      if (_.type(expected) !== 'number' || _.type(delta) !== 'number') {
        throw new Error('the arguments to closeTo or approximately must be numbers');
      }
  
      this.assert(
          Math.abs(obj - expected) <= delta
        , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
        , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
      );
    }
  
    Assertion.addMethod('closeTo', closeTo);
    Assertion.addMethod('approximately', closeTo);
  
    function isSubsetOf(subset, superset, cmp) {
      return subset.every(function(elem) {
        if (!cmp) return superset.indexOf(elem) !== -1;
  
        return superset.some(function(elem2) {
          return cmp(elem, elem2);
        });
      })
    }
  
    /**
     * ### .members(set)
     *
     * Asserts that the target is a superset of `set`,
     * or that the target and `set` have the same strictly-equal (===) members.
     * Alternately, if the `deep` flag is set, set members are compared for deep
     * equality.
     *
     *     expect([1, 2, 3]).to.include.members([3, 2]);
     *     expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
     *
     *     expect([4, 2]).to.have.members([2, 4]);
     *     expect([5, 2]).to.not.have.members([5, 2, 1]);
     *
     *     expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
     *
     * @name members
     * @param {Array} set
     * @param {String} message _optional_
     * @api public
     */
  
    Assertion.addMethod('members', function (subset, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
  
      new Assertion(obj).to.be.an('array');
      new Assertion(subset).to.be.an('array');
  
      var cmp = flag(this, 'deep') ? _.eql : undefined;
  
      if (flag(this, 'contains')) {
        return this.assert(
            isSubsetOf(subset, obj, cmp)
          , 'expected #{this} to be a superset of #{act}'
          , 'expected #{this} to not be a superset of #{act}'
          , obj
          , subset
        );
      }
  
      this.assert(
          isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
          , 'expected #{this} to have the same members as #{act}'
          , 'expected #{this} to not have the same members as #{act}'
          , obj
          , subset
      );
    });
  
    /**
     * ### .oneOf(list)
     *
     * Assert that a value appears somewhere in the top level of array `list`.
     *
     *     expect('a').to.be.oneOf(['a', 'b', 'c']);
     *     expect(9).to.not.be.oneOf(['z']);
     *     expect([3]).to.not.be.oneOf([1, 2, [3]]);
     *
     *     var three = [3];
     *     // for object-types, contents are not compared
     *     expect(three).to.not.be.oneOf([1, 2, [3]]);
     *     // comparing references works
     *     expect(three).to.be.oneOf([1, 2, three]);
     *
     * @name oneOf
     * @param {Array<*>} list
     * @param {String} message _optional_
     * @api public
     */
  
    function oneOf (list, msg) {
      if (msg) flag(this, 'message', msg);
      var expected = flag(this, 'object');
      new Assertion(list).to.be.an('array');
  
      this.assert(
          list.indexOf(expected) > -1
        , 'expected #{this} to be one of #{exp}'
        , 'expected #{this} to not be one of #{exp}'
        , list
        , expected
      );
    }
  
    Assertion.addMethod('oneOf', oneOf);
  
  
    /**
     * ### .change(function)
     *
     * Asserts that a function changes an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val += 3 };
     *     var noChangeFn = function() { return 'foo' + 'bar'; }
     *     expect(fn).to.change(obj, 'val');
     *     expect(noChangFn).to.not.change(obj, 'val')
     *
     * @name change
     * @alias changes
     * @alias Change
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    function assertChanges (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        initial !== object[prop]
        , 'expected .' + prop + ' to change'
        , 'expected .' + prop + ' to not change'
      );
    }
  
    Assertion.addChainableMethod('change', assertChanges);
    Assertion.addChainableMethod('changes', assertChanges);
  
    /**
     * ### .increase(function)
     *
     * Asserts that a function increases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 15 };
     *     expect(fn).to.increase(obj, 'val');
     *
     * @name increase
     * @alias increases
     * @alias Increase
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    function assertIncreases (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        object[prop] - initial > 0
        , 'expected .' + prop + ' to increase'
        , 'expected .' + prop + ' to not increase'
      );
    }
  
    Assertion.addChainableMethod('increase', assertIncreases);
    Assertion.addChainableMethod('increases', assertIncreases);
  
    /**
     * ### .decrease(function)
     *
     * Asserts that a function decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 5 };
     *     expect(fn).to.decrease(obj, 'val');
     *
     * @name decrease
     * @alias decreases
     * @alias Decrease
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    function assertDecreases (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        object[prop] - initial < 0
        , 'expected .' + prop + ' to decrease'
        , 'expected .' + prop + ' to not decrease'
      );
    }
  
    Assertion.addChainableMethod('decrease', assertDecreases);
    Assertion.addChainableMethod('decreases', assertDecreases);
  
    /**
     * ### .extensible
     *
     * Asserts that the target is extensible (can have new properties added to
     * it).
     *
     *     var nonExtensibleObject = Object.preventExtensions({});
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freeze({});
     *
     *     expect({}).to.be.extensible;
     *     expect(nonExtensibleObject).to.not.be.extensible;
     *     expect(sealedObject).to.not.be.extensible;
     *     expect(frozenObject).to.not.be.extensible;
     *
     * @name extensible
     * @api public
     */
  
    Assertion.addProperty('extensible', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false.
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isExtensible;
  
      try {
        isExtensible = Object.isExtensible(obj);
      } catch (err) {
        if (err instanceof TypeError) isExtensible = false;
        else throw err;
      }
  
      this.assert(
        isExtensible
        , 'expected #{this} to be extensible'
        , 'expected #{this} to not be extensible'
      );
    });
  
    /**
     * ### .sealed
     *
     * Asserts that the target is sealed (cannot have new properties added to it
     * and its existing properties cannot be removed).
     *
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freeze({});
     *
     *     expect(sealedObject).to.be.sealed;
     *     expect(frozenObject).to.be.sealed;
     *     expect({}).to.not.be.sealed;
     *
     * @name sealed
     * @api public
     */
  
    Assertion.addProperty('sealed', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true.
      // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isSealed;
  
      try {
        isSealed = Object.isSealed(obj);
      } catch (err) {
        if (err instanceof TypeError) isSealed = true;
        else throw err;
      }
  
      this.assert(
        isSealed
        , 'expected #{this} to be sealed'
        , 'expected #{this} to not be sealed'
      );
    });
  
    /**
     * ### .frozen
     *
     * Asserts that the target is frozen (cannot have new properties added to it
     * and its existing properties cannot be modified).
     *
     *     var frozenObject = Object.freeze({});
     *
     *     expect(frozenObject).to.be.frozen;
     *     expect({}).to.not.be.frozen;
     *
     * @name frozen
     * @api public
     */
  
    Assertion.addProperty('frozen', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true.
      // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isFrozen;
  
      try {
        isFrozen = Object.isFrozen(obj);
      } catch (err) {
        if (err instanceof TypeError) isFrozen = true;
        else throw err;
      }
  
      this.assert(
        isFrozen
        , 'expected #{this} to be frozen'
        , 'expected #{this} to not be frozen'
      );
    });
  };
  
  },{}],19:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  
  module.exports = function (chai, util) {
  
    /*!
     * Chai dependencies.
     */
  
    var Assertion = chai.Assertion
      , flag = util.flag;
  
    /*!
     * Module export.
     */
  
    /**
     * ### assert(expression, message)
     *
     * Write your own test expressions.
     *
     *     assert('foo' !== 'bar', 'foo is not bar');
     *     assert(Array.isArray([]), 'empty arrays are arrays');
     *
     * @param {Mixed} expression to test for truthiness
     * @param {String} message to display on error
     * @name assert
     * @api public
     */
  
    var assert = chai.assert = function (express, errmsg) {
      var test = new Assertion(null, null, chai.assert);
      test.assert(
          express
        , errmsg
        , '[ negation message unavailable ]'
      );
    };
  
    /**
     * ### .fail(actual, expected, [message], [operator])
     *
     * Throw a failure. Node.js `assert` module-compatible.
     *
     * @name fail
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @param {String} operator
     * @api public
     */
  
    assert.fail = function (actual, expected, message, operator) {
      message = message || 'assert.fail()';
      throw new chai.AssertionError(message, {
          actual: actual
        , expected: expected
        , operator: operator
      }, assert.fail);
    };
  
    /**
     * ### .isOk(object, [message])
     *
     * Asserts that `object` is truthy.
     *
     *     assert.isOk('everything', 'everything is ok');
     *     assert.isOk(false, 'this will fail');
     *
     * @name isOk
     * @alias ok
     * @param {Mixed} object to test
     * @param {String} message
     * @api public
     */
  
    assert.isOk = function (val, msg) {
      new Assertion(val, msg).is.ok;
    };
  
    /**
     * ### .isNotOk(object, [message])
     *
     * Asserts that `object` is falsy.
     *
     *     assert.isNotOk('everything', 'this will fail');
     *     assert.isNotOk(false, 'this will pass');
     *
     * @name isNotOk
     * @alias notOk
     * @param {Mixed} object to test
     * @param {String} message
     * @api public
     */
  
    assert.isNotOk = function (val, msg) {
      new Assertion(val, msg).is.not.ok;
    };
  
    /**
     * ### .equal(actual, expected, [message])
     *
     * Asserts non-strict equality (`==`) of `actual` and `expected`.
     *
     *     assert.equal(3, '3', '== coerces values to strings');
     *
     * @name equal
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.equal = function (act, exp, msg) {
      var test = new Assertion(act, msg, assert.equal);
  
      test.assert(
          exp == flag(test, 'object')
        , 'expected #{this} to equal #{exp}'
        , 'expected #{this} to not equal #{act}'
        , exp
        , act
      );
    };
  
    /**
     * ### .notEqual(actual, expected, [message])
     *
     * Asserts non-strict inequality (`!=`) of `actual` and `expected`.
     *
     *     assert.notEqual(3, 4, 'these numbers are not equal');
     *
     * @name notEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.notEqual = function (act, exp, msg) {
      var test = new Assertion(act, msg, assert.notEqual);
  
      test.assert(
          exp != flag(test, 'object')
        , 'expected #{this} to not equal #{exp}'
        , 'expected #{this} to equal #{act}'
        , exp
        , act
      );
    };
  
    /**
     * ### .strictEqual(actual, expected, [message])
     *
     * Asserts strict equality (`===`) of `actual` and `expected`.
     *
     *     assert.strictEqual(true, true, 'these booleans are strictly equal');
     *
     * @name strictEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.strictEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.equal(exp);
    };
  
    /**
     * ### .notStrictEqual(actual, expected, [message])
     *
     * Asserts strict inequality (`!==`) of `actual` and `expected`.
     *
     *     assert.notStrictEqual(3, '3', 'no coercion for strict equality');
     *
     * @name notStrictEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.notStrictEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.not.equal(exp);
    };
  
    /**
     * ### .deepEqual(actual, expected, [message])
     *
     * Asserts that `actual` is deeply equal to `expected`.
     *
     *     assert.deepEqual({ tea: 'green' }, { tea: 'green' });
     *
     * @name deepEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.deepEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.eql(exp);
    };
  
    /**
     * ### .notDeepEqual(actual, expected, [message])
     *
     * Assert that `actual` is not deeply equal to `expected`.
     *
     *     assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
     *
     * @name notDeepEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @api public
     */
  
    assert.notDeepEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.not.eql(exp);
    };
  
     /**
     * ### .isAbove(valueToCheck, valueToBeAbove, [message])
     *
     * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`
     *
     *     assert.isAbove(5, 2, '5 is strictly greater than 2');
     *
     * @name isAbove
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAbove
     * @param {String} message
     * @api public
     */
  
    assert.isAbove = function (val, abv, msg) {
      new Assertion(val, msg).to.be.above(abv);
    };
  
     /**
     * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message])
     *
     * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast`
     *
     *     assert.isAtLeast(5, 2, '5 is greater or equal to 2');
     *     assert.isAtLeast(3, 3, '3 is greater or equal to 3');
     *
     * @name isAtLeast
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAtLeast
     * @param {String} message
     * @api public
     */
  
    assert.isAtLeast = function (val, atlst, msg) {
      new Assertion(val, msg).to.be.least(atlst);
    };
  
     /**
     * ### .isBelow(valueToCheck, valueToBeBelow, [message])
     *
     * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`
     *
     *     assert.isBelow(3, 6, '3 is strictly less than 6');
     *
     * @name isBelow
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeBelow
     * @param {String} message
     * @api public
     */
  
    assert.isBelow = function (val, blw, msg) {
      new Assertion(val, msg).to.be.below(blw);
    };
  
     /**
     * ### .isAtMost(valueToCheck, valueToBeAtMost, [message])
     *
     * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost`
     *
     *     assert.isAtMost(3, 6, '3 is less than or equal to 6');
     *     assert.isAtMost(4, 4, '4 is less than or equal to 4');
     *
     * @name isAtMost
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAtMost
     * @param {String} message
     * @api public
     */
  
    assert.isAtMost = function (val, atmst, msg) {
      new Assertion(val, msg).to.be.most(atmst);
    };
  
    /**
     * ### .isTrue(value, [message])
     *
     * Asserts that `value` is true.
     *
     *     var teaServed = true;
     *     assert.isTrue(teaServed, 'the tea has been served');
     *
     * @name isTrue
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isTrue = function (val, msg) {
      new Assertion(val, msg).is['true'];
    };
  
    /**
     * ### .isNotTrue(value, [message])
     *
     * Asserts that `value` is not true.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotTrue(tea, 'great, time for tea!');
     *
     * @name isNotTrue
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotTrue = function (val, msg) {
      new Assertion(val, msg).to.not.equal(true);
    };
  
    /**
     * ### .isFalse(value, [message])
     *
     * Asserts that `value` is false.
     *
     *     var teaServed = false;
     *     assert.isFalse(teaServed, 'no tea yet? hmm...');
     *
     * @name isFalse
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isFalse = function (val, msg) {
      new Assertion(val, msg).is['false'];
    };
  
    /**
     * ### .isNotFalse(value, [message])
     *
     * Asserts that `value` is not false.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotFalse(tea, 'great, time for tea!');
     *
     * @name isNotFalse
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotFalse = function (val, msg) {
      new Assertion(val, msg).to.not.equal(false);
    };
  
    /**
     * ### .isNull(value, [message])
     *
     * Asserts that `value` is null.
     *
     *     assert.isNull(err, 'there was no error');
     *
     * @name isNull
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNull = function (val, msg) {
      new Assertion(val, msg).to.equal(null);
    };
  
    /**
     * ### .isNotNull(value, [message])
     *
     * Asserts that `value` is not null.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotNull(tea, 'great, time for tea!');
     *
     * @name isNotNull
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotNull = function (val, msg) {
      new Assertion(val, msg).to.not.equal(null);
    };
  
    /**
     * ### .isNaN
     * Asserts that value is NaN
     *
     *    assert.isNaN('foo', 'foo is NaN');
     *
     * @name isNaN
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNaN = function (val, msg) {
      new Assertion(val, msg).to.be.NaN;
    };
  
    /**
     * ### .isNotNaN
     * Asserts that value is not NaN
     *
     *    assert.isNotNaN(4, '4 is not NaN');
     *
     * @name isNotNaN
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
    assert.isNotNaN = function (val, msg) {
      new Assertion(val, msg).not.to.be.NaN;
    };
  
    /**
     * ### .isUndefined(value, [message])
     *
     * Asserts that `value` is `undefined`.
     *
     *     var tea;
     *     assert.isUndefined(tea, 'no tea defined');
     *
     * @name isUndefined
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isUndefined = function (val, msg) {
      new Assertion(val, msg).to.equal(undefined);
    };
  
    /**
     * ### .isDefined(value, [message])
     *
     * Asserts that `value` is not `undefined`.
     *
     *     var tea = 'cup of chai';
     *     assert.isDefined(tea, 'tea has been defined');
     *
     * @name isDefined
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isDefined = function (val, msg) {
      new Assertion(val, msg).to.not.equal(undefined);
    };
  
    /**
     * ### .isFunction(value, [message])
     *
     * Asserts that `value` is a function.
     *
     *     function serveTea() { return 'cup of tea'; };
     *     assert.isFunction(serveTea, 'great, we can have tea now');
     *
     * @name isFunction
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isFunction = function (val, msg) {
      new Assertion(val, msg).to.be.a('function');
    };
  
    /**
     * ### .isNotFunction(value, [message])
     *
     * Asserts that `value` is _not_ a function.
     *
     *     var serveTea = [ 'heat', 'pour', 'sip' ];
     *     assert.isNotFunction(serveTea, 'great, we have listed the steps');
     *
     * @name isNotFunction
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotFunction = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('function');
    };
  
    /**
     * ### .isObject(value, [message])
     *
     * Asserts that `value` is an object (as revealed by
     * `Object.prototype.toString`).
     *
     *     var selection = { name: 'Chai', serve: 'with spices' };
     *     assert.isObject(selection, 'tea selection is an object');
     *
     * @name isObject
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isObject = function (val, msg) {
      new Assertion(val, msg).to.be.a('object');
    };
  
    /**
     * ### .isNotObject(value, [message])
     *
     * Asserts that `value` is _not_ an object.
     *
     *     var selection = 'chai'
     *     assert.isNotObject(selection, 'tea selection is not an object');
     *     assert.isNotObject(null, 'null is not an object');
     *
     * @name isNotObject
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotObject = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('object');
    };
  
    /**
     * ### .isArray(value, [message])
     *
     * Asserts that `value` is an array.
     *
     *     var menu = [ 'green', 'chai', 'oolong' ];
     *     assert.isArray(menu, 'what kind of tea do we want?');
     *
     * @name isArray
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isArray = function (val, msg) {
      new Assertion(val, msg).to.be.an('array');
    };
  
    /**
     * ### .isNotArray(value, [message])
     *
     * Asserts that `value` is _not_ an array.
     *
     *     var menu = 'green|chai|oolong';
     *     assert.isNotArray(menu, 'what kind of tea do we want?');
     *
     * @name isNotArray
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotArray = function (val, msg) {
      new Assertion(val, msg).to.not.be.an('array');
    };
  
    /**
     * ### .isString(value, [message])
     *
     * Asserts that `value` is a string.
     *
     *     var teaOrder = 'chai';
     *     assert.isString(teaOrder, 'order placed');
     *
     * @name isString
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isString = function (val, msg) {
      new Assertion(val, msg).to.be.a('string');
    };
  
    /**
     * ### .isNotString(value, [message])
     *
     * Asserts that `value` is _not_ a string.
     *
     *     var teaOrder = 4;
     *     assert.isNotString(teaOrder, 'order placed');
     *
     * @name isNotString
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotString = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('string');
    };
  
    /**
     * ### .isNumber(value, [message])
     *
     * Asserts that `value` is a number.
     *
     *     var cups = 2;
     *     assert.isNumber(cups, 'how many cups');
     *
     * @name isNumber
     * @param {Number} value
     * @param {String} message
     * @api public
     */
  
    assert.isNumber = function (val, msg) {
      new Assertion(val, msg).to.be.a('number');
    };
  
    /**
     * ### .isNotNumber(value, [message])
     *
     * Asserts that `value` is _not_ a number.
     *
     *     var cups = '2 cups please';
     *     assert.isNotNumber(cups, 'how many cups');
     *
     * @name isNotNumber
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotNumber = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('number');
    };
  
    /**
     * ### .isBoolean(value, [message])
     *
     * Asserts that `value` is a boolean.
     *
     *     var teaReady = true
     *       , teaServed = false;
     *
     *     assert.isBoolean(teaReady, 'is the tea ready');
     *     assert.isBoolean(teaServed, 'has tea been served');
     *
     * @name isBoolean
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isBoolean = function (val, msg) {
      new Assertion(val, msg).to.be.a('boolean');
    };
  
    /**
     * ### .isNotBoolean(value, [message])
     *
     * Asserts that `value` is _not_ a boolean.
     *
     *     var teaReady = 'yep'
     *       , teaServed = 'nope';
     *
     *     assert.isNotBoolean(teaReady, 'is the tea ready');
     *     assert.isNotBoolean(teaServed, 'has tea been served');
     *
     * @name isNotBoolean
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.isNotBoolean = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('boolean');
    };
  
    /**
     * ### .typeOf(value, name, [message])
     *
     * Asserts that `value`'s type is `name`, as determined by
     * `Object.prototype.toString`.
     *
     *     assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
     *     assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
     *     assert.typeOf('tea', 'string', 'we have a string');
     *     assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
     *     assert.typeOf(null, 'null', 'we have a null');
     *     assert.typeOf(undefined, 'undefined', 'we have an undefined');
     *
     * @name typeOf
     * @param {Mixed} value
     * @param {String} name
     * @param {String} message
     * @api public
     */
  
    assert.typeOf = function (val, type, msg) {
      new Assertion(val, msg).to.be.a(type);
    };
  
    /**
     * ### .notTypeOf(value, name, [message])
     *
     * Asserts that `value`'s type is _not_ `name`, as determined by
     * `Object.prototype.toString`.
     *
     *     assert.notTypeOf('tea', 'number', 'strings are not numbers');
     *
     * @name notTypeOf
     * @param {Mixed} value
     * @param {String} typeof name
     * @param {String} message
     * @api public
     */
  
    assert.notTypeOf = function (val, type, msg) {
      new Assertion(val, msg).to.not.be.a(type);
    };
  
    /**
     * ### .instanceOf(object, constructor, [message])
     *
     * Asserts that `value` is an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , chai = new Tea('chai');
     *
     *     assert.instanceOf(chai, Tea, 'chai is an instance of tea');
     *
     * @name instanceOf
     * @param {Object} object
     * @param {Constructor} constructor
     * @param {String} message
     * @api public
     */
  
    assert.instanceOf = function (val, type, msg) {
      new Assertion(val, msg).to.be.instanceOf(type);
    };
  
    /**
     * ### .notInstanceOf(object, constructor, [message])
     *
     * Asserts `value` is not an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , chai = new String('chai');
     *
     *     assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
     *
     * @name notInstanceOf
     * @param {Object} object
     * @param {Constructor} constructor
     * @param {String} message
     * @api public
     */
  
    assert.notInstanceOf = function (val, type, msg) {
      new Assertion(val, msg).to.not.be.instanceOf(type);
    };
  
    /**
     * ### .include(haystack, needle, [message])
     *
     * Asserts that `haystack` includes `needle`. Works
     * for strings and arrays.
     *
     *     assert.include('foobar', 'bar', 'foobar contains string "bar"');
     *     assert.include([ 1, 2, 3 ], 3, 'array contains value');
     *
     * @name include
     * @param {Array|String} haystack
     * @param {Mixed} needle
     * @param {String} message
     * @api public
     */
  
    assert.include = function (exp, inc, msg) {
      new Assertion(exp, msg, assert.include).include(inc);
    };
  
    /**
     * ### .notInclude(haystack, needle, [message])
     *
     * Asserts that `haystack` does not include `needle`. Works
     * for strings and arrays.
     *
     *     assert.notInclude('foobar', 'baz', 'string not include substring');
     *     assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
     *
     * @name notInclude
     * @param {Array|String} haystack
     * @param {Mixed} needle
     * @param {String} message
     * @api public
     */
  
    assert.notInclude = function (exp, inc, msg) {
      new Assertion(exp, msg, assert.notInclude).not.include(inc);
    };
  
    /**
     * ### .match(value, regexp, [message])
     *
     * Asserts that `value` matches the regular expression `regexp`.
     *
     *     assert.match('foobar', /^foo/, 'regexp matches');
     *
     * @name match
     * @param {Mixed} value
     * @param {RegExp} regexp
     * @param {String} message
     * @api public
     */
  
    assert.match = function (exp, re, msg) {
      new Assertion(exp, msg).to.match(re);
    };
  
    /**
     * ### .notMatch(value, regexp, [message])
     *
     * Asserts that `value` does not match the regular expression `regexp`.
     *
     *     assert.notMatch('foobar', /^foo/, 'regexp does not match');
     *
     * @name notMatch
     * @param {Mixed} value
     * @param {RegExp} regexp
     * @param {String} message
     * @api public
     */
  
    assert.notMatch = function (exp, re, msg) {
      new Assertion(exp, msg).to.not.match(re);
    };
  
    /**
     * ### .property(object, property, [message])
     *
     * Asserts that `object` has a property named by `property`.
     *
     *     assert.property({ tea: { green: 'matcha' }}, 'tea');
     *
     * @name property
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @api public
     */
  
    assert.property = function (obj, prop, msg) {
      new Assertion(obj, msg).to.have.property(prop);
    };
  
    /**
     * ### .notProperty(object, property, [message])
     *
     * Asserts that `object` does _not_ have a property named by `property`.
     *
     *     assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
     *
     * @name notProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @api public
     */
  
    assert.notProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.not.have.property(prop);
    };
  
    /**
     * ### .deepProperty(object, property, [message])
     *
     * Asserts that `object` has a property named by `property`, which can be a
     * string using dot- and bracket-notation for deep reference.
     *
     *     assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
     *
     * @name deepProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @api public
     */
  
    assert.deepProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.have.deep.property(prop);
    };
  
    /**
     * ### .notDeepProperty(object, property, [message])
     *
     * Asserts that `object` does _not_ have a property named by `property`, which
     * can be a string using dot- and bracket-notation for deep reference.
     *
     *     assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
     *
     * @name notDeepProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @api public
     */
  
    assert.notDeepProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.not.have.deep.property(prop);
    };
  
    /**
     * ### .propertyVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property` with value given
     * by `value`.
     *
     *     assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
     *
     * @name propertyVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.propertyVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.have.property(prop, val);
    };
  
    /**
     * ### .propertyNotVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property`, but with a value
     * different from that given by `value`.
     *
     *     assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
     *
     * @name propertyNotVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.propertyNotVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.not.have.property(prop, val);
    };
  
    /**
     * ### .deepPropertyVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property` with value given
     * by `value`. `property` can use dot- and bracket-notation for deep
     * reference.
     *
     *     assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
     *
     * @name deepPropertyVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.deepPropertyVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.have.deep.property(prop, val);
    };
  
    /**
     * ### .deepPropertyNotVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property`, but with a value
     * different from that given by `value`. `property` can use dot- and
     * bracket-notation for deep reference.
     *
     *     assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
     *
     * @name deepPropertyNotVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @api public
     */
  
    assert.deepPropertyNotVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.not.have.deep.property(prop, val);
    };
  
    /**
     * ### .lengthOf(object, length, [message])
     *
     * Asserts that `object` has a `length` property with the expected value.
     *
     *     assert.lengthOf([1,2,3], 3, 'array has length of 3');
     *     assert.lengthOf('foobar', 6, 'string has length of 6');
     *
     * @name lengthOf
     * @param {Mixed} object
     * @param {Number} length
     * @param {String} message
     * @api public
     */
  
    assert.lengthOf = function (exp, len, msg) {
      new Assertion(exp, msg).to.have.length(len);
    };
  
    /**
     * ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
     *
     * Asserts that `function` will throw an error that is an instance of
     * `constructor`, or alternately that it will throw an error with message
     * matching `regexp`.
     *
     *     assert.throws(fn, 'function throws a reference error');
     *     assert.throws(fn, /function throws a reference error/);
     *     assert.throws(fn, ReferenceError);
     *     assert.throws(fn, ReferenceError, 'function throws a reference error');
     *     assert.throws(fn, ReferenceError, /function throws a reference error/);
     *
     * @name throws
     * @alias throw
     * @alias Throw
     * @param {Function} function
     * @param {ErrorConstructor} constructor
     * @param {RegExp} regexp
     * @param {String} message
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @api public
     */
  
    assert.throws = function (fn, errt, errs, msg) {
      if ('string' === typeof errt || errt instanceof RegExp) {
        errs = errt;
        errt = null;
      }
  
      var assertErr = new Assertion(fn, msg).to.throw(errt, errs);
      return flag(assertErr, 'object');
    };
  
    /**
     * ### .doesNotThrow(function, [constructor/regexp], [message])
     *
     * Asserts that `function` will _not_ throw an error that is an instance of
     * `constructor`, or alternately that it will not throw an error with message
     * matching `regexp`.
     *
     *     assert.doesNotThrow(fn, Error, 'function does not throw');
     *
     * @name doesNotThrow
     * @param {Function} function
     * @param {ErrorConstructor} constructor
     * @param {RegExp} regexp
     * @param {String} message
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @api public
     */
  
    assert.doesNotThrow = function (fn, type, msg) {
      if ('string' === typeof type) {
        msg = type;
        type = null;
      }
  
      new Assertion(fn, msg).to.not.Throw(type);
    };
  
    /**
     * ### .operator(val1, operator, val2, [message])
     *
     * Compares two values using `operator`.
     *
     *     assert.operator(1, '<', 2, 'everything is ok');
     *     assert.operator(1, '>', 2, 'this will fail');
     *
     * @name operator
     * @param {Mixed} val1
     * @param {String} operator
     * @param {Mixed} val2
     * @param {String} message
     * @api public
     */
  
    assert.operator = function (val, operator, val2, msg) {
      var ok;
      switch(operator) {
        case '==':
          ok = val == val2;
          break;
        case '===':
          ok = val === val2;
          break;
        case '>':
          ok = val > val2;
          break;
        case '>=':
          ok = val >= val2;
          break;
        case '<':
          ok = val < val2;
          break;
        case '<=':
          ok = val <= val2;
          break;
        case '!=':
          ok = val != val2;
          break;
        case '!==':
          ok = val !== val2;
          break;
        default:
          throw new Error('Invalid operator "' + operator + '"');
      }
      var test = new Assertion(ok, msg);
      test.assert(
          true === flag(test, 'object')
        , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
        , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
    };
  
    /**
     * ### .closeTo(actual, expected, delta, [message])
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     assert.closeTo(1.5, 1, 0.5, 'numbers are close');
     *
     * @name closeTo
     * @param {Number} actual
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message
     * @api public
     */
  
    assert.closeTo = function (act, exp, delta, msg) {
      new Assertion(act, msg).to.be.closeTo(exp, delta);
    };
  
    /**
     * ### .approximately(actual, expected, delta, [message])
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     assert.approximately(1.5, 1, 0.5, 'numbers are close');
     *
     * @name approximately
     * @param {Number} actual
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message
     * @api public
     */
  
    assert.approximately = function (act, exp, delta, msg) {
      new Assertion(act, msg).to.be.approximately(exp, delta);
    };
  
    /**
     * ### .sameMembers(set1, set2, [message])
     *
     * Asserts that `set1` and `set2` have the same members.
     * Order is not taken into account.
     *
     *     assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
     *
     * @name sameMembers
     * @param {Array} set1
     * @param {Array} set2
     * @param {String} message
     * @api public
     */
  
    assert.sameMembers = function (set1, set2, msg) {
      new Assertion(set1, msg).to.have.same.members(set2);
    }
  
    /**
     * ### .sameDeepMembers(set1, set2, [message])
     *
     * Asserts that `set1` and `set2` have the same members - using a deep equality checking.
     * Order is not taken into account.
     *
     *     assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members');
     *
     * @name sameDeepMembers
     * @param {Array} set1
     * @param {Array} set2
     * @param {String} message
     * @api public
     */
  
    assert.sameDeepMembers = function (set1, set2, msg) {
      new Assertion(set1, msg).to.have.same.deep.members(set2);
    }
  
    /**
     * ### .includeMembers(superset, subset, [message])
     *
     * Asserts that `subset` is included in `superset`.
     * Order is not taken into account.
     *
     *     assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
     *
     * @name includeMembers
     * @param {Array} superset
     * @param {Array} subset
     * @param {String} message
     * @api public
     */
  
    assert.includeMembers = function (superset, subset, msg) {
      new Assertion(superset, msg).to.include.members(subset);
    }
  
    /**
     * ### .oneOf(inList, list, [message])
     *
     * Asserts that non-object, non-array value `inList` appears in the flat array `list`.
     *
     *     assert.oneOf(1, [ 2, 1 ], 'Not found in list');
     *
     * @name oneOf
     * @param {*} inList
     * @param {Array<*>} list
     * @param {String} message
     * @api public
     */
  
    assert.oneOf = function (inList, list, msg) {
      new Assertion(inList, msg).to.be.oneOf(list);
    }
  
     /**
     * ### .changes(function, object, property)
     *
     * Asserts that a function changes the value of a property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 22 };
     *     assert.changes(fn, obj, 'val');
     *
     * @name changes
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.changes = function (fn, obj, prop) {
      new Assertion(fn).to.change(obj, prop);
    }
  
     /**
     * ### .doesNotChange(function, object, property)
     *
     * Asserts that a function does not changes the value of a property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { console.log('foo'); };
     *     assert.doesNotChange(fn, obj, 'val');
     *
     * @name doesNotChange
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.doesNotChange = function (fn, obj, prop) {
      new Assertion(fn).to.not.change(obj, prop);
    }
  
     /**
     * ### .increases(function, object, property)
     *
     * Asserts that a function increases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 13 };
     *     assert.increases(fn, obj, 'val');
     *
     * @name increases
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.increases = function (fn, obj, prop) {
      new Assertion(fn).to.increase(obj, prop);
    }
  
     /**
     * ### .doesNotIncrease(function, object, property)
     *
     * Asserts that a function does not increase object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 8 };
     *     assert.doesNotIncrease(fn, obj, 'val');
     *
     * @name doesNotIncrease
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.doesNotIncrease = function (fn, obj, prop) {
      new Assertion(fn).to.not.increase(obj, prop);
    }
  
     /**
     * ### .decreases(function, object, property)
     *
     * Asserts that a function decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 5 };
     *     assert.decreases(fn, obj, 'val');
     *
     * @name decreases
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.decreases = function (fn, obj, prop) {
      new Assertion(fn).to.decrease(obj, prop);
    }
  
     /**
     * ### .doesNotDecrease(function, object, property)
     *
     * Asserts that a function does not decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 15 };
     *     assert.doesNotDecrease(fn, obj, 'val');
     *
     * @name doesNotDecrease
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @api public
     */
  
    assert.doesNotDecrease = function (fn, obj, prop) {
      new Assertion(fn).to.not.decrease(obj, prop);
    }
  
    /*!
     * ### .ifError(object)
     *
     * Asserts if value is not a false value, and throws if it is a true value.
     * This is added to allow for chai to be a drop-in replacement for Node's
     * assert class.
     *
     *     var err = new Error('I am a custom error');
     *     assert.ifError(err); // Rethrows err!
     *
     * @name ifError
     * @param {Object} object
     * @api public
     */
  
    assert.ifError = function (val) {
      if (val) {
        throw(val);
      }
    };
  
    /**
     * ### .isExtensible(object)
     *
     * Asserts that `object` is extensible (can have new properties added to it).
     *
     *     assert.isExtensible({});
     *
     * @name isExtensible
     * @alias extensible
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isExtensible = function (obj, msg) {
      new Assertion(obj, msg).to.be.extensible;
    };
  
    /**
     * ### .isNotExtensible(object)
     *
     * Asserts that `object` is _not_ extensible.
     *
     *     var nonExtensibleObject = Object.preventExtensions({});
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freese({});
     *
     *     assert.isNotExtensible(nonExtensibleObject);
     *     assert.isNotExtensible(sealedObject);
     *     assert.isNotExtensible(frozenObject);
     *
     * @name isNotExtensible
     * @alias notExtensible
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isNotExtensible = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.extensible;
    };
  
    /**
     * ### .isSealed(object)
     *
     * Asserts that `object` is sealed (cannot have new properties added to it
     * and its existing properties cannot be removed).
     *
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.seal({});
     *
     *     assert.isSealed(sealedObject);
     *     assert.isSealed(frozenObject);
     *
     * @name isSealed
     * @alias sealed
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isSealed = function (obj, msg) {
      new Assertion(obj, msg).to.be.sealed;
    };
  
    /**
     * ### .isNotSealed(object)
     *
     * Asserts that `object` is _not_ sealed.
     *
     *     assert.isNotSealed({});
     *
     * @name isNotSealed
     * @alias notSealed
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isNotSealed = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.sealed;
    };
  
    /**
     * ### .isFrozen(object)
     *
     * Asserts that `object` is frozen (cannot have new properties added to it
     * and its existing properties cannot be modified).
     *
     *     var frozenObject = Object.freeze({});
     *     assert.frozen(frozenObject);
     *
     * @name isFrozen
     * @alias frozen
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isFrozen = function (obj, msg) {
      new Assertion(obj, msg).to.be.frozen;
    };
  
    /**
     * ### .isNotFrozen(object)
     *
     * Asserts that `object` is _not_ frozen.
     *
     *     assert.isNotFrozen({});
     *
     * @name isNotFrozen
     * @alias notFrozen
     * @param {Object} object
     * @param {String} message _optional_
     * @api public
     */
  
    assert.isNotFrozen = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.frozen;
    };
  
    /*!
     * Aliases.
     */
  
    (function alias(name, as){
      assert[as] = assert[name];
      return alias;
    })
    ('isOk', 'ok')
    ('isNotOk', 'notOk')
    ('throws', 'throw')
    ('throws', 'Throw')
    ('isExtensible', 'extensible')
    ('isNotExtensible', 'notExtensible')
    ('isSealed', 'sealed')
    ('isNotSealed', 'notSealed')
    ('isFrozen', 'frozen')
    ('isNotFrozen', 'notFrozen');
  };
  
  },{}],20:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, util) {
    chai.expect = function (val, message) {
      return new chai.Assertion(val, message);
    };
  
    /**
     * ### .fail(actual, expected, [message], [operator])
     *
     * Throw a failure.
     *
     * @name fail
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @param {String} operator
     * @api public
     */
  
    chai.expect.fail = function (actual, expected, message, operator) {
      message = message || 'expect.fail()';
      throw new chai.AssertionError(message, {
          actual: actual
        , expected: expected
        , operator: operator
      }, chai.expect.fail);
    };
  };
  
  },{}],21:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, util) {
    var Assertion = chai.Assertion;
  
    function loadShould () {
      // explicitly define this method as function as to have it's name to include as `ssfi`
      function shouldGetter() {
        if (this instanceof String || this instanceof Number || this instanceof Boolean ) {
          return new Assertion(this.valueOf(), null, shouldGetter);
        }
        return new Assertion(this, null, shouldGetter);
      }
      function shouldSetter(value) {
        // See https://github.com/chaijs/chai/issues/86: this makes
        // `whatever.should = someValue` actually set `someValue`, which is
        // especially useful for `global.should = require('chai').should()`.
        //
        // Note that we have to use [[DefineProperty]] instead of [[Put]]
        // since otherwise we would trigger this very setter!
        Object.defineProperty(this, 'should', {
          value: value,
          enumerable: true,
          configurable: true,
          writable: true
        });
      }
      // modify Object.prototype to have `should`
      Object.defineProperty(Object.prototype, 'should', {
        set: shouldSetter
        , get: shouldGetter
        , configurable: true
      });
  
      var should = {};
  
      /**
       * ### .fail(actual, expected, [message], [operator])
       *
       * Throw a failure.
       *
       * @name fail
       * @param {Mixed} actual
       * @param {Mixed} expected
       * @param {String} message
       * @param {String} operator
       * @api public
       */
  
      should.fail = function (actual, expected, message, operator) {
        message = message || 'should.fail()';
        throw new chai.AssertionError(message, {
            actual: actual
          , expected: expected
          , operator: operator
        }, should.fail);
      };
  
      should.equal = function (val1, val2, msg) {
        new Assertion(val1, msg).to.equal(val2);
      };
  
      should.Throw = function (fn, errt, errs, msg) {
        new Assertion(fn, msg).to.Throw(errt, errs);
      };
  
      should.exist = function (val, msg) {
        new Assertion(val, msg).to.exist;
      }
  
      // negation
      should.not = {}
  
      should.not.equal = function (val1, val2, msg) {
        new Assertion(val1, msg).to.not.equal(val2);
      };
  
      should.not.Throw = function (fn, errt, errs, msg) {
        new Assertion(fn, msg).to.not.Throw(errt, errs);
      };
  
      should.not.exist = function (val, msg) {
        new Assertion(val, msg).to.not.exist;
      }
  
      should['throw'] = should['Throw'];
      should.not['throw'] = should.not['Throw'];
  
      return should;
    };
  
    chai.should = loadShould;
    chai.Should = loadShould;
  };
  
  },{}],22:[function(require,module,exports){
  /*!
   * Chai - addChainingMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependencies
   */
  
  var transferFlags = require('./transferFlags');
  var flag = require('./flag');
  var config = require('../config');
  
  /*!
   * Module variables
   */
  
  // Check whether `__proto__` is supported
  var hasProtoSupport = '__proto__' in Object;
  
  // Without `__proto__` support, this module will need to add properties to a function.
  // However, some Function.prototype methods cannot be overwritten,
  // and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).
  var excludeNames = /^(?:length|name|arguments|caller)$/;
  
  // Cache `Function` properties
  var call  = Function.prototype.call,
      apply = Function.prototype.apply;
  
  /**
   * ### addChainableMethod (ctx, name, method, chainingBehavior)
   *
   * Adds a method to an object, such that the method can also be chained.
   *
   *     utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.equal(str);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);
   *
   * The result can then be used as both a method assertion, executing both `method` and
   * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.
   *
   *     expect(fooStr).to.be.foo('bar');
   *     expect(fooStr).to.be.foo.equal('foo');
   *
   * @param {Object} ctx object to which the method is added
   * @param {String} name of method to add
   * @param {Function} method function to be used for `name`, when called
   * @param {Function} chainingBehavior function to be called every time the property is accessed
   * @name addChainableMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method, chainingBehavior) {
    if (typeof chainingBehavior !== 'function') {
      chainingBehavior = function () { };
    }
  
    var chainableBehavior = {
        method: method
      , chainingBehavior: chainingBehavior
    };
  
    // save the methods so we can overwrite them later, if we need to.
    if (!ctx.__methods) {
      ctx.__methods = {};
    }
    ctx.__methods[name] = chainableBehavior;
  
    Object.defineProperty(ctx, name,
      { get: function () {
          chainableBehavior.chainingBehavior.call(this);
  
          var assert = function assert() {
            var old_ssfi = flag(this, 'ssfi');
            if (old_ssfi && config.includeStack === false)
              flag(this, 'ssfi', assert);
            var result = chainableBehavior.method.apply(this, arguments);
            return result === undefined ? this : result;
          };
  
          // Use `__proto__` if available
          if (hasProtoSupport) {
            // Inherit all properties from the object by replacing the `Function` prototype
            var prototype = assert.__proto__ = Object.create(this);
            // Restore the `call` and `apply` methods from `Function`
            prototype.call = call;
            prototype.apply = apply;
          }
          // Otherwise, redefine all properties (slow!)
          else {
            var asserterNames = Object.getOwnPropertyNames(ctx);
            asserterNames.forEach(function (asserterName) {
              if (!excludeNames.test(asserterName)) {
                var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
                Object.defineProperty(assert, asserterName, pd);
              }
            });
          }
  
          transferFlags(this, assert);
          return assert;
        }
      , configurable: true
    });
  };
  
  },{"../config":17,"./flag":26,"./transferFlags":42}],23:[function(require,module,exports){
  /*!
   * Chai - addMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var config = require('../config');
  
  /**
   * ### .addMethod (ctx, name, method)
   *
   * Adds a method to the prototype of an object.
   *
   *     utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.equal(str);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addMethod('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(fooStr).to.be.foo('bar');
   *
   * @param {Object} ctx object to which the method is added
   * @param {String} name of method to add
   * @param {Function} method function to be used for name
   * @name addMethod
   * @api public
   */
  var flag = require('./flag');
  
  module.exports = function (ctx, name, method) {
    ctx[name] = function () {
      var old_ssfi = flag(this, 'ssfi');
      if (old_ssfi && config.includeStack === false)
        flag(this, 'ssfi', ctx[name]);
      var result = method.apply(this, arguments);
      return result === undefined ? this : result;
    };
  };
  
  },{"../config":17,"./flag":26}],24:[function(require,module,exports){
  /*!
   * Chai - addProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var config = require('../config');
  var flag = require('./flag');
  
  /**
   * ### addProperty (ctx, name, getter)
   *
   * Adds a property to the prototype of an object.
   *
   *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.instanceof(Foo);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addProperty('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.be.foo;
   *
   * @param {Object} ctx object to which the property is added
   * @param {String} name of property to add
   * @param {Function} getter function to be used for name
   * @name addProperty
   * @api public
   */
  
  module.exports = function (ctx, name, getter) {
    Object.defineProperty(ctx, name,
      { get: function addProperty() {
          var old_ssfi = flag(this, 'ssfi');
          if (old_ssfi && config.includeStack === false)
            flag(this, 'ssfi', addProperty);
  
          var result = getter.call(this);
          return result === undefined ? this : result;
        }
      , configurable: true
    });
  };
  
  },{"../config":17,"./flag":26}],25:[function(require,module,exports){
  /*!
   * Chai - expectTypes utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### expectTypes(obj, types)
   *
   * Ensures that the object being tested against is of a valid type.
   *
   *     utils.expectTypes(this, ['array', 'object', 'string']);
   *
   * @param {Mixed} obj constructed Assertion
   * @param {Array} type A list of allowed types for this assertion
   * @name expectTypes
   * @api public
   */
  
  var AssertionError = require('assertion-error');
  var flag = require('./flag');
  var type = require('type-detect');
  
  module.exports = function (obj, types) {
    var obj = flag(obj, 'object');
    types = types.map(function (t) { return t.toLowerCase(); });
    types.sort();
  
    // Transforms ['lorem', 'ipsum'] into 'a lirum, or an ipsum'
    var str = types.map(function (t, index) {
      var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a';
      var or = types.length > 1 && index === types.length - 1 ? 'or ' : '';
      return or + art + ' ' + t;
    }).join(', ');
  
    if (!types.some(function (expected) { return type(obj) === expected; })) {
      throw new AssertionError(
        'object tested must be ' + str + ', but ' + type(obj) + ' given'
      );
    }
  };
  
  },{"./flag":26,"assertion-error":7,"type-detect":263}],26:[function(require,module,exports){
  /*!
   * Chai - flag utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### flag(object, key, [value])
   *
   * Get or set a flag value on an object. If a
   * value is provided it will be set, else it will
   * return the currently set value or `undefined` if
   * the value is not set.
   *
   *     utils.flag(this, 'foo', 'bar'); // setter
   *     utils.flag(this, 'foo'); // getter, returns `bar`
   *
   * @param {Object} object constructed Assertion
   * @param {String} key
   * @param {Mixed} value (optional)
   * @name flag
   * @api private
   */
  
  module.exports = function (obj, key, value) {
    var flags = obj.__flags || (obj.__flags = Object.create(null));
    if (arguments.length === 3) {
      flags[key] = value;
    } else {
      return flags[key];
    }
  };
  
  },{}],27:[function(require,module,exports){
  /*!
   * Chai - getActual utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * # getActual(object, [actual])
   *
   * Returns the `actual` value for an Assertion
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   */
  
  module.exports = function (obj, args) {
    return args.length > 4 ? args[4] : obj._obj;
  };
  
  },{}],28:[function(require,module,exports){
  /*!
   * Chai - getEnumerableProperties utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### .getEnumerableProperties(object)
   *
   * This allows the retrieval of enumerable property names of an object,
   * inherited or not.
   *
   * @param {Object} object
   * @returns {Array}
   * @name getEnumerableProperties
   * @api public
   */
  
  module.exports = function getEnumerableProperties(object) {
    var result = [];
    for (var name in object) {
      result.push(name);
    }
    return result;
  };
  
  },{}],29:[function(require,module,exports){
  /*!
   * Chai - message composition utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var flag = require('./flag')
    , getActual = require('./getActual')
    , inspect = require('./inspect')
    , objDisplay = require('./objDisplay');
  
  /**
   * ### .getMessage(object, message, negateMessage)
   *
   * Construct the error message based on flags
   * and template tags. Template tags will return
   * a stringified inspection of the object referenced.
   *
   * Message template tags:
   * - `#{this}` current asserted object
   * - `#{act}` actual value
   * - `#{exp}` expected value
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   * @name getMessage
   * @api public
   */
  
  module.exports = function (obj, args) {
    var negate = flag(obj, 'negate')
      , val = flag(obj, 'object')
      , expected = args[3]
      , actual = getActual(obj, args)
      , msg = negate ? args[2] : args[1]
      , flagMsg = flag(obj, 'message');
  
    if(typeof msg === "function") msg = msg();
    msg = msg || '';
    msg = msg
      .replace(/#{this}/g, objDisplay(val))
      .replace(/#{act}/g, objDisplay(actual))
      .replace(/#{exp}/g, objDisplay(expected));
  
    return flagMsg ? flagMsg + ': ' + msg : msg;
  };
  
  },{"./flag":26,"./getActual":27,"./inspect":36,"./objDisplay":37}],30:[function(require,module,exports){
  /*!
   * Chai - getName utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * # getName(func)
   *
   * Gets the name of a function, in a cross-browser way.
   *
   * @param {Function} a function (usually a constructor)
   */
  
  module.exports = function (func) {
    if (func.name) return func.name;
  
    var match = /^\s?function ([^(]*)\(/.exec(func);
    return match && match[1] ? match[1] : "";
  };
  
  },{}],31:[function(require,module,exports){
  /*!
   * Chai - getPathInfo utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var hasProperty = require('./hasProperty');
  
  /**
   * ### .getPathInfo(path, object)
   *
   * This allows the retrieval of property info in an
   * object given a string path.
   *
   * The path info consists of an object with the
   * following properties:
   *
   * * parent - The parent object of the property referenced by `path`
   * * name - The name of the final property, a number if it was an array indexer
   * * value - The value of the property, if it exists, otherwise `undefined`
   * * exists - Whether the property exists or not
   *
   * @param {String} path
   * @param {Object} object
   * @returns {Object} info
   * @name getPathInfo
   * @api public
   */
  
  module.exports = function getPathInfo(path, obj) {
    var parsed = parsePath(path),
        last = parsed[parsed.length - 1];
  
    var info = {
      parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj,
      name: last.p || last.i,
      value: _getPathValue(parsed, obj)
    };
    info.exists = hasProperty(info.name, info.parent);
  
    return info;
  };
  
  
  /*!
   * ## parsePath(path)
   *
   * Helper function used to parse string object
   * paths. Use in conjunction with `_getPathValue`.
   *
   *      var parsed = parsePath('myobject.property.subprop');
   *
   * ### Paths:
   *
   * * Can be as near infinitely deep and nested
   * * Arrays are also valid using the formal `myobject.document[3].property`.
   * * Literal dots and brackets (not delimiter) must be backslash-escaped.
   *
   * @param {String} path
   * @returns {Object} parsed
   * @api private
   */
  
  function parsePath (path) {
    var str = path.replace(/([^\\])\[/g, '$1.[')
      , parts = str.match(/(\\\.|[^.]+?)+/g);
    return parts.map(function (value) {
      var re = /^\[(\d+)\]$/
        , mArr = re.exec(value);
      if (mArr) return { i: parseFloat(mArr[1]) };
      else return { p: value.replace(/\\([.\[\]])/g, '$1') };
    });
  }
  
  
  /*!
   * ## _getPathValue(parsed, obj)
   *
   * Helper companion function for `.parsePath` that returns
   * the value located at the parsed address.
   *
   *      var value = getPathValue(parsed, obj);
   *
   * @param {Object} parsed definition from `parsePath`.
   * @param {Object} object to search against
   * @param {Number} object to search against
   * @returns {Object|Undefined} value
   * @api private
   */
  
  function _getPathValue (parsed, obj, index) {
    var tmp = obj
      , res;
  
    index = (index === undefined ? parsed.length : index);
  
    for (var i = 0, l = index; i < l; i++) {
      var part = parsed[i];
      if (tmp) {
        if ('undefined' !== typeof part.p)
          tmp = tmp[part.p];
        else if ('undefined' !== typeof part.i)
          tmp = tmp[part.i];
        if (i == (l - 1)) res = tmp;
      } else {
        res = undefined;
      }
    }
    return res;
  }
  
  },{"./hasProperty":34}],32:[function(require,module,exports){
  /*!
   * Chai - getPathValue utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * @see https://github.com/logicalparadox/filtr
   * MIT Licensed
   */
  
  var getPathInfo = require('./getPathInfo');
  
  /**
   * ### .getPathValue(path, object)
   *
   * This allows the retrieval of values in an
   * object given a string path.
   *
   *     var obj = {
   *         prop1: {
   *             arr: ['a', 'b', 'c']
   *           , str: 'Hello'
   *         }
   *       , prop2: {
   *             arr: [ { nested: 'Universe' } ]
   *           , str: 'Hello again!'
   *         }
   *     }
   *
   * The following would be the results.
   *
   *     getPathValue('prop1.str', obj); // Hello
   *     getPathValue('prop1.att[2]', obj); // b
   *     getPathValue('prop2.arr[0].nested', obj); // Universe
   *
   * @param {String} path
   * @param {Object} object
   * @returns {Object} value or `undefined`
   * @name getPathValue
   * @api public
   */
  module.exports = function(path, obj) {
    var info = getPathInfo(path, obj);
    return info.value;
  }; 
  
  },{"./getPathInfo":31}],33:[function(require,module,exports){
  /*!
   * Chai - getProperties utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### .getProperties(object)
   *
   * This allows the retrieval of property names of an object, enumerable or not,
   * inherited or not.
   *
   * @param {Object} object
   * @returns {Array}
   * @name getProperties
   * @api public
   */
  
  module.exports = function getProperties(object) {
    var result = Object.getOwnPropertyNames(object);
  
    function addProperty(property) {
      if (result.indexOf(property) === -1) {
        result.push(property);
      }
    }
  
    var proto = Object.getPrototypeOf(object);
    while (proto !== null) {
      Object.getOwnPropertyNames(proto).forEach(addProperty);
      proto = Object.getPrototypeOf(proto);
    }
  
    return result;
  };
  
  },{}],34:[function(require,module,exports){
  /*!
   * Chai - hasProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var type = require('type-detect');
  
  /**
   * ### .hasProperty(object, name)
   *
   * This allows checking whether an object has
   * named property or numeric array index.
   *
   * Basically does the same thing as the `in`
   * operator but works properly with natives
   * and null/undefined values.
   *
   *     var obj = {
   *         arr: ['a', 'b', 'c']
   *       , str: 'Hello'
   *     }
   *
   * The following would be the results.
   *
   *     hasProperty('str', obj);  // true
   *     hasProperty('constructor', obj);  // true
   *     hasProperty('bar', obj);  // false
   *     
   *     hasProperty('length', obj.str); // true
   *     hasProperty(1, obj.str);  // true
   *     hasProperty(5, obj.str);  // false
   *
   *     hasProperty('length', obj.arr);  // true
   *     hasProperty(2, obj.arr);  // true
   *     hasProperty(3, obj.arr);  // false
   *
   * @param {Objuect} object
   * @param {String|Number} name
   * @returns {Boolean} whether it exists
   * @name getPathInfo
   * @api public
   */
  
  var literals = {
      'number': Number
    , 'string': String
  };
  
  module.exports = function hasProperty(name, obj) {
    var ot = type(obj);
  
    // Bad Object, obviously no props at all
    if(ot === 'null' || ot === 'undefined')
      return false;
  
    // The `in` operator does not work with certain literals
    // box these before the check
    if(literals[ot] && typeof obj !== 'object')
      obj = new literals[ot](obj);
  
    return name in obj;
  };
  
  },{"type-detect":263}],35:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Main exports
   */
  
  var exports = module.exports = {};
  
  /*!
   * test utility
   */
  
  exports.test = require('./test');
  
  /*!
   * type utility
   */
  
  exports.type = require('type-detect');
  
  /*!
   * expectTypes utility
   */
  exports.expectTypes = require('./expectTypes');
  
  /*!
   * message utility
   */
  
  exports.getMessage = require('./getMessage');
  
  /*!
   * actual utility
   */
  
  exports.getActual = require('./getActual');
  
  /*!
   * Inspect util
   */
  
  exports.inspect = require('./inspect');
  
  /*!
   * Object Display util
   */
  
  exports.objDisplay = require('./objDisplay');
  
  /*!
   * Flag utility
   */
  
  exports.flag = require('./flag');
  
  /*!
   * Flag transferring utility
   */
  
  exports.transferFlags = require('./transferFlags');
  
  /*!
   * Deep equal utility
   */
  
  exports.eql = require('deep-eql');
  
  /*!
   * Deep path value
   */
  
  exports.getPathValue = require('./getPathValue');
  
  /*!
   * Deep path info
   */
  
  exports.getPathInfo = require('./getPathInfo');
  
  /*!
   * Check if a property exists
   */
  
  exports.hasProperty = require('./hasProperty');
  
  /*!
   * Function name
   */
  
  exports.getName = require('./getName');
  
  /*!
   * add Property
   */
  
  exports.addProperty = require('./addProperty');
  
  /*!
   * add Method
   */
  
  exports.addMethod = require('./addMethod');
  
  /*!
   * overwrite Property
   */
  
  exports.overwriteProperty = require('./overwriteProperty');
  
  /*!
   * overwrite Method
   */
  
  exports.overwriteMethod = require('./overwriteMethod');
  
  /*!
   * Add a chainable method
   */
  
  exports.addChainableMethod = require('./addChainableMethod');
  
  /*!
   * Overwrite chainable method
   */
  
  exports.overwriteChainableMethod = require('./overwriteChainableMethod');
  
  },{"./addChainableMethod":22,"./addMethod":23,"./addProperty":24,"./expectTypes":25,"./flag":26,"./getActual":27,"./getMessage":29,"./getName":30,"./getPathInfo":31,"./getPathValue":32,"./hasProperty":34,"./inspect":36,"./objDisplay":37,"./overwriteChainableMethod":38,"./overwriteMethod":39,"./overwriteProperty":40,"./test":41,"./transferFlags":42,"deep-eql":47,"type-detect":263}],36:[function(require,module,exports){
  // This is (almost) directly from Node.js utils
  // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
  
  var getName = require('./getName');
  var getProperties = require('./getProperties');
  var getEnumerableProperties = require('./getEnumerableProperties');
  
  module.exports = inspect;
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Boolean} showHidden Flag that shows hidden (not enumerable)
   *    properties of objects.
   * @param {Number} depth Depth in which to descend in object. Default is 2.
   * @param {Boolean} colors Flag to turn on ANSI escape codes to color the
   *    output. Default is false (no coloring).
   */
  function inspect(obj, showHidden, depth, colors) {
    var ctx = {
      showHidden: showHidden,
      seen: [],
      stylize: function (str) { return str; }
    };
    return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
  }
  
  // Returns true if object is a DOM element.
  var isDOMElement = function (object) {
    if (typeof HTMLElement === 'object') {
      return object instanceof HTMLElement;
    } else {
      return object &&
        typeof object === 'object' &&
        object.nodeType === 1 &&
        typeof object.nodeName === 'string';
    }
  };
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (value && typeof value.inspect === 'function' &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes);
      if (typeof ret !== 'string') {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // If this is a DOM element, try to get the outer HTML.
    if (isDOMElement(value)) {
      if ('outerHTML' in value) {
        return value.outerHTML;
        // This value does not have an outerHTML attribute,
        //   it could still be an XML element
      } else {
        // Attempt to serialize it
        try {
          if (document.xmlVersion) {
            var xmlSerializer = new XMLSerializer();
            return xmlSerializer.serializeToString(value);
          } else {
            // Firefox 11- do not support outerHTML
            //   It does, however, support innerHTML
            //   Use the following to render the element
            var ns = "http://www.w3.org/1999/xhtml";
            var container = document.createElementNS(ns, '_');
  
            container.appendChild(value.cloneNode(false));
            html = container.innerHTML
              .replace('><', '>' + value.innerHTML + '<');
            container.innerHTML = '';
            return html;
          }
        } catch (err) {
          // This could be a non-native DOM implementation,
          //   continue with the normal flow:
          //   printing the element as if it is an object.
        }
      }
    }
  
    // Look up the keys of the object.
    var visibleKeys = getEnumerableProperties(value);
    var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
  
    // Some type of object without properties can be shortcutted.
    // In IE, errors have a single `stack` property, or if they are vanilla `Error`,
    // a `stack` plus `description` property; ignore those for consistency.
    if (keys.length === 0 || (isError(value) && (
        (keys.length === 1 && keys[0] === 'stack') ||
        (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
       ))) {
      if (typeof value === 'function') {
        var name = getName(value);
        var nameSuffix = name ? ': ' + name : '';
        return ctx.stylize('[Function' + nameSuffix + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (typeof value === 'function') {
      var name = getName(value);
      var nameSuffix = name ? ': ' + name : '';
      base = ' [Function' + nameSuffix + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      return formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    switch (typeof value) {
      case 'undefined':
        return ctx.stylize('undefined', 'undefined');
  
      case 'string':
        var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                                 .replace(/'/g, "\\'")
                                                 .replace(/\\"/g, '"') + '\'';
        return ctx.stylize(simple, 'string');
  
      case 'number':
        if (value === 0 && (1/value) === -Infinity) {
          return ctx.stylize('-0', 'number');
        }
        return ctx.stylize('' + value, 'number');
  
      case 'boolean':
        return ctx.stylize('' + value, 'boolean');
    }
    // For some reason typeof null is "object", so special case here.
    if (value === null) {
      return ctx.stylize('null', 'null');
    }
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (Object.prototype.hasOwnProperty.call(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str;
    if (value.__lookupGetter__) {
      if (value.__lookupGetter__(key)) {
        if (value.__lookupSetter__(key)) {
          str = ctx.stylize('[Getter/Setter]', 'special');
        } else {
          str = ctx.stylize('[Getter]', 'special');
        }
      } else {
        if (value.__lookupSetter__(key)) {
          str = ctx.stylize('[Setter]', 'special');
        }
      }
    }
    if (visibleKeys.indexOf(key) < 0) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(value[key]) < 0) {
        if (recurseTimes === null) {
          str = formatValue(ctx, value[key], null);
        } else {
          str = formatValue(ctx, value[key], recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (typeof name === 'undefined') {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  function isArray(ar) {
    return Array.isArray(ar) ||
           (typeof ar === 'object' && objectToString(ar) === '[object Array]');
  }
  
  function isRegExp(re) {
    return typeof re === 'object' && objectToString(re) === '[object RegExp]';
  }
  
  function isDate(d) {
    return typeof d === 'object' && objectToString(d) === '[object Date]';
  }
  
  function isError(e) {
    return typeof e === 'object' && objectToString(e) === '[object Error]';
  }
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  },{"./getEnumerableProperties":28,"./getName":30,"./getProperties":33}],37:[function(require,module,exports){
  /*!
   * Chai - flag utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var inspect = require('./inspect');
  var config = require('../config');
  
  /**
   * ### .objDisplay (object)
   *
   * Determines if an object or an array matches
   * criteria to be inspected in-line for error
   * messages or should be truncated.
   *
   * @param {Mixed} javascript object to inspect
   * @name objDisplay
   * @api public
   */
  
  module.exports = function (obj) {
    var str = inspect(obj)
      , type = Object.prototype.toString.call(obj);
  
    if (config.truncateThreshold && str.length >= config.truncateThreshold) {
      if (type === '[object Function]') {
        return !obj.name || obj.name === ''
          ? '[Function]'
          : '[Function: ' + obj.name + ']';
      } else if (type === '[object Array]') {
        return '[ Array(' + obj.length + ') ]';
      } else if (type === '[object Object]') {
        var keys = Object.keys(obj)
          , kstr = keys.length > 2
            ? keys.splice(0, 2).join(', ') + ', ...'
            : keys.join(', ');
        return '{ Object (' + kstr + ') }';
      } else {
        return str;
      }
    } else {
      return str;
    }
  };
  
  },{"../config":17,"./inspect":36}],38:[function(require,module,exports){
  /*!
   * Chai - overwriteChainableMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteChainableMethod (ctx, name, method, chainingBehavior)
   *
   * Overwites an already existing chainable method
   * and provides access to the previous function or
   * property.  Must return functions to be used for
   * name.
   *
   *     utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
   *       function (_super) {
   *       }
   *     , function (_super) {
   *       }
   *     );
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteChainableMethod('foo', fn, fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.have.length(3);
   *     expect(myFoo).to.have.length.above(3);
   *
   * @param {Object} ctx object whose method / property is to be overwritten
   * @param {String} name of method / property to overwrite
   * @param {Function} method function that returns a function to be used for name
   * @param {Function} chainingBehavior function that returns a function to be used for property
   * @name overwriteChainableMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method, chainingBehavior) {
    var chainableBehavior = ctx.__methods[name];
  
    var _chainingBehavior = chainableBehavior.chainingBehavior;
    chainableBehavior.chainingBehavior = function () {
      var result = chainingBehavior(_chainingBehavior).call(this);
      return result === undefined ? this : result;
    };
  
    var _method = chainableBehavior.method;
    chainableBehavior.method = function () {
      var result = method(_method).apply(this, arguments);
      return result === undefined ? this : result;
    };
  };
  
  },{}],39:[function(require,module,exports){
  /*!
   * Chai - overwriteMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteMethod (ctx, name, fn)
   *
   * Overwites an already existing method and provides
   * access to previous function. Must return function
   * to be used for name.
   *
   *     utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {
   *       return function (str) {
   *         var obj = utils.flag(this, 'object');
   *         if (obj instanceof Foo) {
   *           new chai.Assertion(obj.value).to.equal(str);
   *         } else {
   *           _super.apply(this, arguments);
   *         }
   *       }
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteMethod('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.equal('bar');
   *
   * @param {Object} ctx object whose method is to be overwritten
   * @param {String} name of method to overwrite
   * @param {Function} method function that returns a function to be used for name
   * @name overwriteMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method) {
    var _method = ctx[name]
      , _super = function () { return this; };
  
    if (_method && 'function' === typeof _method)
      _super = _method;
  
    ctx[name] = function () {
      var result = method(_super).apply(this, arguments);
      return result === undefined ? this : result;
    }
  };
  
  },{}],40:[function(require,module,exports){
  /*!
   * Chai - overwriteProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteProperty (ctx, name, fn)
   *
   * Overwites an already existing property getter and provides
   * access to previous value. Must return function to use as getter.
   *
   *     utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {
   *       return function () {
   *         var obj = utils.flag(this, 'object');
   *         if (obj instanceof Foo) {
   *           new chai.Assertion(obj.name).to.equal('bar');
   *         } else {
   *           _super.call(this);
   *         }
   *       }
   *     });
   *
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteProperty('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.be.ok;
   *
   * @param {Object} ctx object whose property is to be overwritten
   * @param {String} name of property to overwrite
   * @param {Function} getter function that returns a getter function to be used for name
   * @name overwriteProperty
   * @api public
   */
  
  module.exports = function (ctx, name, getter) {
    var _get = Object.getOwnPropertyDescriptor(ctx, name)
      , _super = function () {};
  
    if (_get && 'function' === typeof _get.get)
      _super = _get.get
  
    Object.defineProperty(ctx, name,
      { get: function () {
          var result = getter(_super).call(this);
          return result === undefined ? this : result;
        }
      , configurable: true
    });
  };
  
  },{}],41:[function(require,module,exports){
  /*!
   * Chai - test utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var flag = require('./flag');
  
  /**
   * # test(object, expression)
   *
   * Test and object for expression.
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   */
  
  module.exports = function (obj, args) {
    var negate = flag(obj, 'negate')
      , expr = args[0];
    return negate ? !expr : expr;
  };
  
  },{"./flag":26}],42:[function(require,module,exports){
  /*!
   * Chai - transferFlags utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### transferFlags(assertion, object, includeAll = true)
   *
   * Transfer all the flags for `assertion` to `object`. If
   * `includeAll` is set to `false`, then the base Chai
   * assertion flags (namely `object`, `ssfi`, and `message`)
   * will not be transferred.
   *
   *
   *     var newAssertion = new Assertion();
   *     utils.transferFlags(assertion, newAssertion);
   *
   *     var anotherAsseriton = new Assertion(myObj);
   *     utils.transferFlags(assertion, anotherAssertion, false);
   *
   * @param {Assertion} assertion the assertion to transfer the flags from
   * @param {Object} object the object to transfer the flags to; usually a new assertion
   * @param {Boolean} includeAll
   * @name transferFlags
   * @api private
   */
  
  module.exports = function (assertion, object, includeAll) {
    var flags = assertion.__flags || (assertion.__flags = Object.create(null));
  
    if (!object.__flags) {
      object.__flags = Object.create(null);
    }
  
    includeAll = arguments.length === 3 ? includeAll : true;
  
    for (var flag in flags) {
      if (includeAll ||
          (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
        object.__flags[flag] = flags[flag];
      }
    }
  };
  
  },{}],43:[function(require,module,exports){
  (function (Buffer){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  
  function isArray(arg) {
    if (Array.isArray) {
      return Array.isArray(arg);
    }
    return objectToString(arg) === '[object Array]';
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = Buffer.isBuffer;
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  }).call(this,{"isBuffer":require("../../is-buffer/index.js")})
  },{"../../is-buffer/index.js":197}],44:[function(require,module,exports){
  "use strict"
  
  var createThunk = require("./lib/thunk.js")
  
  function Procedure() {
    this.argTypes = []
    this.shimArgs = []
    this.arrayArgs = []
    this.arrayBlockIndices = []
    this.scalarArgs = []
    this.offsetArgs = []
    this.offsetArgIndex = []
    this.indexArgs = []
    this.shapeArgs = []
    this.funcName = ""
    this.pre = null
    this.body = null
    this.post = null
    this.debug = false
  }
  
  function compileCwise(user_args) {
    //Create procedure
    var proc = new Procedure()
    
    //Parse blocks
    proc.pre    = user_args.pre
    proc.body   = user_args.body
    proc.post   = user_args.post
  
    //Parse arguments
    var proc_args = user_args.args.slice(0)
    proc.argTypes = proc_args
    for(var i=0; i<proc_args.length; ++i) {
      var arg_type = proc_args[i]
      if(arg_type === "array" || (typeof arg_type === "object" && arg_type.blockIndices)) {
        proc.argTypes[i] = "array"
        proc.arrayArgs.push(i)
        proc.arrayBlockIndices.push(arg_type.blockIndices ? arg_type.blockIndices : 0)
        proc.shimArgs.push("array" + i)
        if(i < proc.pre.args.length && proc.pre.args[i].count>0) {
          throw new Error("cwise: pre() block may not reference array args")
        }
        if(i < proc.post.args.length && proc.post.args[i].count>0) {
          throw new Error("cwise: post() block may not reference array args")
        }
      } else if(arg_type === "scalar") {
        proc.scalarArgs.push(i)
        proc.shimArgs.push("scalar" + i)
      } else if(arg_type === "index") {
        proc.indexArgs.push(i)
        if(i < proc.pre.args.length && proc.pre.args[i].count > 0) {
          throw new Error("cwise: pre() block may not reference array index")
        }
        if(i < proc.body.args.length && proc.body.args[i].lvalue) {
          throw new Error("cwise: body() block may not write to array index")
        }
        if(i < proc.post.args.length && proc.post.args[i].count > 0) {
          throw new Error("cwise: post() block may not reference array index")
        }
      } else if(arg_type === "shape") {
        proc.shapeArgs.push(i)
        if(i < proc.pre.args.length && proc.pre.args[i].lvalue) {
          throw new Error("cwise: pre() block may not write to array shape")
        }
        if(i < proc.body.args.length && proc.body.args[i].lvalue) {
          throw new Error("cwise: body() block may not write to array shape")
        }
        if(i < proc.post.args.length && proc.post.args[i].lvalue) {
          throw new Error("cwise: post() block may not write to array shape")
        }
      } else if(typeof arg_type === "object" && arg_type.offset) {
        proc.argTypes[i] = "offset"
        proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset })
        proc.offsetArgIndex.push(i)
      } else {
        throw new Error("cwise: Unknown argument type " + proc_args[i])
      }
    }
    
    //Make sure at least one array argument was specified
    if(proc.arrayArgs.length <= 0) {
      throw new Error("cwise: No array arguments specified")
    }
    
    //Make sure arguments are correct
    if(proc.pre.args.length > proc_args.length) {
      throw new Error("cwise: Too many arguments in pre() block")
    }
    if(proc.body.args.length > proc_args.length) {
      throw new Error("cwise: Too many arguments in body() block")
    }
    if(proc.post.args.length > proc_args.length) {
      throw new Error("cwise: Too many arguments in post() block")
    }
  
    //Check debug flag
    proc.debug = !!user_args.printCode || !!user_args.debug
    
    //Retrieve name
    proc.funcName = user_args.funcName || "cwise"
    
    //Read in block size
    proc.blockSize = user_args.blockSize || 64
  
    return createThunk(proc)
  }
  
  module.exports = compileCwise
  
  },{"./lib/thunk.js":46}],45:[function(require,module,exports){
  "use strict"
  
  var uniq = require("uniq")
  
  // This function generates very simple loops analogous to how you typically traverse arrays (the outermost loop corresponds to the slowest changing index, the innermost loop to the fastest changing index)
  // TODO: If two arrays have the same strides (and offsets) there is potential for decreasing the number of "pointers" and related variables. The drawback is that the type signature would become more specific and that there would thus be less potential for caching, but it might still be worth it, especially when dealing with large numbers of arguments.
  function innerFill(order, proc, body) {
    var dimension = order.length
      , nargs = proc.arrayArgs.length
      , has_index = proc.indexArgs.length>0
      , code = []
      , vars = []
      , idx=0, pidx=0, i, j
    for(i=0; i<dimension; ++i) { // Iteration variables
      vars.push(["i",i,"=0"].join(""))
    }
    //Compute scan deltas
    for(j=0; j<nargs; ++j) {
      for(i=0; i<dimension; ++i) {
        pidx = idx
        idx = order[i]
        if(i === 0) { // The innermost/fastest dimension's delta is simply its stride
          vars.push(["d",j,"s",i,"=t",j,"p",idx].join(""))
        } else { // For other dimensions the delta is basically the stride minus something which essentially "rewinds" the previous (more inner) dimension
          vars.push(["d",j,"s",i,"=(t",j,"p",idx,"-s",pidx,"*t",j,"p",pidx,")"].join(""))
        }
      }
    }
    code.push("var " + vars.join(","))
    //Scan loop
    for(i=dimension-1; i>=0; --i) { // Start at largest stride and work your way inwards
      idx = order[i]
      code.push(["for(i",i,"=0;i",i,"<s",idx,";++i",i,"){"].join(""))
    }
    //Push body of inner loop
    code.push(body)
    //Advance scan pointers
    for(i=0; i<dimension; ++i) {
      pidx = idx
      idx = order[i]
      for(j=0; j<nargs; ++j) {
        code.push(["p",j,"+=d",j,"s",i].join(""))
      }
      if(has_index) {
        if(i > 0) {
          code.push(["index[",pidx,"]-=s",pidx].join(""))
        }
        code.push(["++index[",idx,"]"].join(""))
      }
      code.push("}")
    }
    return code.join("\n")
  }
  
  // Generate "outer" loops that loop over blocks of data, applying "inner" loops to the blocks by manipulating the local variables in such a way that the inner loop only "sees" the current block.
  // TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary.
  //       I believe the s* are not used elsewhere (in particular, I don't think they're used in the pre/post parts and "shape" is defined independently), so it would be possible to make defining the s* dependent on what loop method is being used.
  function outerFill(matched, order, proc, body) {
    var dimension = order.length
      , nargs = proc.arrayArgs.length
      , blockSize = proc.blockSize
      , has_index = proc.indexArgs.length > 0
      , code = []
    for(var i=0; i<nargs; ++i) {
      code.push(["var offset",i,"=p",i].join(""))
    }
    //Generate loops for unmatched dimensions
    // The order in which these dimensions are traversed is fairly arbitrary (from small stride to large stride, for the first argument)
    // TODO: It would be nice if the order in which these loops are placed would also be somehow "optimal" (at the very least we should check that it really doesn't hurt us if they're not).
    for(var i=matched; i<dimension; ++i) {
      code.push(["for(var j"+i+"=SS[", order[i], "]|0;j", i, ">0;){"].join("")) // Iterate back to front
      code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j).
      code.push(["s",order[i],"=j",i].join(""))
      code.push(["j",i,"=0"].join(""))
      code.push(["}else{s",order[i],"=",blockSize].join(""))
      code.push(["j",i,"-=",blockSize,"}"].join(""))
      if(has_index) {
        code.push(["index[",order[i],"]=j",i].join(""))
      }
    }
    for(var i=0; i<nargs; ++i) {
      var indexStr = ["offset"+i]
      for(var j=matched; j<dimension; ++j) {
        indexStr.push(["j",j,"*t",i,"p",order[j]].join(""))
      }
      code.push(["p",i,"=(",indexStr.join("+"),")"].join(""))
    }
    code.push(innerFill(order, proc, body))
    for(var i=matched; i<dimension; ++i) {
      code.push("}")
    }
    return code.join("\n")
  }
  
  //Count the number of compatible inner orders
  // This is the length of the longest common prefix of the arrays in orders.
  // Each array in orders lists the dimensions of the correspond ndarray in order of increasing stride.
  // This is thus the maximum number of dimensions that can be efficiently traversed by simple nested loops for all arrays.
  function countMatches(orders) {
    var matched = 0, dimension = orders[0].length
    while(matched < dimension) {
      for(var j=1; j<orders.length; ++j) {
        if(orders[j][matched] !== orders[0][matched]) {
          return matched
        }
      }
      ++matched
    }
    return matched
  }
  
  //Processes a block according to the given data types
  // Replaces variable names by different ones, either "local" ones (that are then ferried in and out of the given array) or ones matching the arguments that the function performing the ultimate loop will accept.
  function processBlock(block, proc, dtypes) {
    var code = block.body
    var pre = []
    var post = []
    for(var i=0; i<block.args.length; ++i) {
      var carg = block.args[i]
      if(carg.count <= 0) {
        continue
      }
      var re = new RegExp(carg.name, "g")
      var ptrStr = ""
      var arrNum = proc.arrayArgs.indexOf(i)
      switch(proc.argTypes[i]) {
        case "offset":
          var offArgIndex = proc.offsetArgIndex.indexOf(i)
          var offArg = proc.offsetArgs[offArgIndex]
          arrNum = offArg.array
          ptrStr = "+q" + offArgIndex // Adds offset to the "pointer" in the array
        case "array":
          ptrStr = "p" + arrNum + ptrStr
          var localStr = "l" + i
          var arrStr = "a" + arrNum
          if (proc.arrayBlockIndices[arrNum] === 0) { // Argument to body is just a single value from this array
            if(carg.count === 1) { // Argument/array used only once(?)
              if(dtypes[arrNum] === "generic") {
                if(carg.lvalue) {
                  pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // Is this necessary if the argument is ONLY used as an lvalue? (keep in mind that we can have a += something, so we would actually need to check carg.rvalue)
                  code = code.replace(re, localStr)
                  post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
                } else {
                  code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join(""))
                }
              } else {
                code = code.replace(re, [arrStr, "[", ptrStr, "]"].join(""))
              }
            } else if(dtypes[arrNum] === "generic") {
              pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // TODO: Could we optimize by checking for carg.rvalue?
              code = code.replace(re, localStr)
              if(carg.lvalue) {
                post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
              }
            } else {
              pre.push(["var ", localStr, "=", arrStr, "[", ptrStr, "]"].join("")) // TODO: Could we optimize by checking for carg.rvalue?
              code = code.replace(re, localStr)
              if(carg.lvalue) {
                post.push([arrStr, "[", ptrStr, "]=", localStr].join(""))
              }
            }
          } else { // Argument to body is a "block"
            var reStrArr = [carg.name], ptrStrArr = [ptrStr]
            for(var j=0; j<Math.abs(proc.arrayBlockIndices[arrNum]); j++) {
              reStrArr.push("\\s*\\[([^\\]]+)\\]")
              ptrStrArr.push("$" + (j+1) + "*t" + arrNum + "b" + j) // Matched index times stride
            }
            re = new RegExp(reStrArr.join(""), "g")
            ptrStr = ptrStrArr.join("+")
            if(dtypes[arrNum] === "generic") {
              /*if(carg.lvalue) {
                pre.push(["var ", localStr, "=", arrStr, ".get(", ptrStr, ")"].join("")) // Is this necessary if the argument is ONLY used as an lvalue? (keep in mind that we can have a += something, so we would actually need to check carg.rvalue)
                code = code.replace(re, localStr)
                post.push([arrStr, ".set(", ptrStr, ",", localStr,")"].join(""))
              } else {
                code = code.replace(re, [arrStr, ".get(", ptrStr, ")"].join(""))
              }*/
              throw new Error("cwise: Generic arrays not supported in combination with blocks!")
            } else {
              // This does not produce any local variables, even if variables are used multiple times. It would be possible to do so, but it would complicate things quite a bit.
              code = code.replace(re, [arrStr, "[", ptrStr, "]"].join(""))
            }
          }
        break
        case "scalar":
          code = code.replace(re, "Y" + proc.scalarArgs.indexOf(i))
        break
        case "index":
          code = code.replace(re, "index")
        break
        case "shape":
          code = code.replace(re, "shape")
        break
      }
    }
    return [pre.join("\n"), code, post.join("\n")].join("\n").trim()
  }
  
  function typeSummary(dtypes) {
    var summary = new Array(dtypes.length)
    var allEqual = true
    for(var i=0; i<dtypes.length; ++i) {
      var t = dtypes[i]
      var digits = t.match(/\d+/)
      if(!digits) {
        digits = ""
      } else {
        digits = digits[0]
      }
      if(t.charAt(0) === 0) {
        summary[i] = "u" + t.charAt(1) + digits
      } else {
        summary[i] = t.charAt(0) + digits
      }
      if(i > 0) {
        allEqual = allEqual && summary[i] === summary[i-1]
      }
    }
    if(allEqual) {
      return summary[0]
    }
    return summary.join("")
  }
  
  //Generates a cwise operator
  function generateCWiseOp(proc, typesig) {
  
    //Compute dimension
    // Arrays get put first in typesig, and there are two entries per array (dtype and order), so this gets the number of dimensions in the first array arg.
    var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0
    var orders = new Array(proc.arrayArgs.length)
    var dtypes = new Array(proc.arrayArgs.length)
    for(var i=0; i<proc.arrayArgs.length; ++i) {
      dtypes[i] = typesig[2*i]
      orders[i] = typesig[2*i+1]
    }
    
    //Determine where block and loop indices start and end
    var blockBegin = [], blockEnd = [] // These indices are exposed as blocks
    var loopBegin = [], loopEnd = [] // These indices are iterated over
    var loopOrders = [] // orders restricted to the loop indices
    for(var i=0; i<proc.arrayArgs.length; ++i) {
      if (proc.arrayBlockIndices[i]<0) {
        loopBegin.push(0)
        loopEnd.push(dimension)
        blockBegin.push(dimension)
        blockEnd.push(dimension+proc.arrayBlockIndices[i])
      } else {
        loopBegin.push(proc.arrayBlockIndices[i]) // Non-negative
        loopEnd.push(proc.arrayBlockIndices[i]+dimension)
        blockBegin.push(0)
        blockEnd.push(proc.arrayBlockIndices[i])
      }
      var newOrder = []
      for(var j=0; j<orders[i].length; j++) {
        if (loopBegin[i]<=orders[i][j] && orders[i][j]<loopEnd[i]) {
          newOrder.push(orders[i][j]-loopBegin[i]) // If this is a loop index, put it in newOrder, subtracting loopBegin, to make sure that all loopOrders are using a common set of indices.
        }
      }
      loopOrders.push(newOrder)
    }
  
    //First create arguments for procedure
    var arglist = ["SS"] // SS is the overall shape over which we iterate
    var code = ["'use strict'"]
    var vars = []
    
    for(var j=0; j<dimension; ++j) {
      vars.push(["s", j, "=SS[", j, "]"].join("")) // The limits for each dimension.
    }
    for(var i=0; i<proc.arrayArgs.length; ++i) {
      arglist.push("a"+i) // Actual data array
      arglist.push("t"+i) // Strides
      arglist.push("p"+i) // Offset in the array at which the data starts (also used for iterating over the data)
      
      for(var j=0; j<dimension; ++j) { // Unpack the strides into vars for looping
        vars.push(["t",i,"p",j,"=t",i,"[",loopBegin[i]+j,"]"].join(""))
      }
      
      for(var j=0; j<Math.abs(proc.arrayBlockIndices[i]); ++j) { // Unpack the strides into vars for block iteration
        vars.push(["t",i,"b",j,"=t",i,"[",blockBegin[i]+j,"]"].join(""))
      }
    }
    for(var i=0; i<proc.scalarArgs.length; ++i) {
      arglist.push("Y" + i)
    }
    if(proc.shapeArgs.length > 0) {
      vars.push("shape=SS.slice(0)") // Makes the shape over which we iterate available to the user defined functions (so you can use width/height for example)
    }
    if(proc.indexArgs.length > 0) {
      // Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes.
      var zeros = new Array(dimension)
      for(var i=0; i<dimension; ++i) {
        zeros[i] = "0"
      }
      vars.push(["index=[", zeros.join(","), "]"].join(""))
    }
    for(var i=0; i<proc.offsetArgs.length; ++i) { // Offset arguments used for stencil operations
      var off_arg = proc.offsetArgs[i]
      var init_string = []
      for(var j=0; j<off_arg.offset.length; ++j) {
        if(off_arg.offset[j] === 0) {
          continue
        } else if(off_arg.offset[j] === 1) {
          init_string.push(["t", off_arg.array, "p", j].join(""))      
        } else {
          init_string.push([off_arg.offset[j], "*t", off_arg.array, "p", j].join(""))
        }
      }
      if(init_string.length === 0) {
        vars.push("q" + i + "=0")
      } else {
        vars.push(["q", i, "=", init_string.join("+")].join(""))
      }
    }
  
    //Prepare this variables
    var thisVars = uniq([].concat(proc.pre.thisVars)
                        .concat(proc.body.thisVars)
                        .concat(proc.post.thisVars))
    vars = vars.concat(thisVars)
    code.push("var " + vars.join(","))
    for(var i=0; i<proc.arrayArgs.length; ++i) {
      code.push("p"+i+"|=0")
    }
    
    //Inline prelude
    if(proc.pre.body.length > 3) {
      code.push(processBlock(proc.pre, proc, dtypes))
    }
  
    //Process body
    var body = processBlock(proc.body, proc, dtypes)
    var matched = countMatches(loopOrders)
    if(matched < dimension) {
      code.push(outerFill(matched, loopOrders[0], proc, body)) // TODO: Rather than passing loopOrders[0], it might be interesting to look at passing an order that represents the majority of the arguments for example.
    } else {
      code.push(innerFill(loopOrders[0], proc, body))
    }
  
    //Inline epilog
    if(proc.post.body.length > 3) {
      code.push(processBlock(proc.post, proc, dtypes))
    }
    
    if(proc.debug) {
      console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------")
    }
    
    var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("")
    var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join(""))
    return f()
  }
  module.exports = generateCWiseOp
  
  },{"uniq":266}],46:[function(require,module,exports){
  "use strict"
  
  // The function below is called when constructing a cwise function object, and does the following:
  // A function object is constructed which accepts as argument a compilation function and returns another function.
  // It is this other function that is eventually returned by createThunk, and this function is the one that actually
  // checks whether a certain pattern of arguments has already been used before and compiles new loops as needed.
  // The compilation passed to the first function object is used for compiling new functions.
  // Once this function object is created, it is called with compile as argument, where the first argument of compile
  // is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise).
  // So createThunk roughly works like this:
  // function createThunk(proc) {
  //   var thunk = function(compileBound) {
  //     var CACHED = {}
  //     return function(arrays and scalars) {
  //       if (dtype and order of arrays in CACHED) {
  //         var func = CACHED[dtype and order of arrays]
  //       } else {
  //         var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays)
  //       }
  //       return func(arrays and scalars)
  //     }
  //   }
  //   return thunk(compile.bind1(proc))
  // }
  
  var compile = require("./compile.js")
  
  function createThunk(proc) {
    var code = ["'use strict'", "var CACHED={}"]
    var vars = []
    var thunkName = proc.funcName + "_cwise_thunk"
    
    //Build thunk
    code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join(""))
    var typesig = []
    var string_typesig = []
    var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS).
                      Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")]
    var shapeLengthConditions = [], shapeConditions = []
    // Process array arguments
    for(var i=0; i<proc.arrayArgs.length; ++i) {
      var j = proc.arrayArgs[i]
      vars.push(["t", j, "=array", j, ".dtype,",
                 "r", j, "=array", j, ".order"].join(""))
      typesig.push("t" + j)
      typesig.push("r" + j)
      string_typesig.push("t"+j)
      string_typesig.push("r"+j+".join()")
      proc_args.push("array" + j + ".data")
      proc_args.push("array" + j + ".stride")
      proc_args.push("array" + j + ".offset|0")
      if (i>0) { // Gather conditions to check for shape equality (ignoring block indices)
        shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i])))
        shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]")
      }
    }
    // Check for shape equality
    if (proc.arrayArgs.length > 1) {
      code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')")
      code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {")
      code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')")
      code.push("}")
    }
    // Process scalar arguments
    for(var i=0; i<proc.scalarArgs.length; ++i) {
      proc_args.push("scalar" + proc.scalarArgs[i])
    }
    // Check for cached function (and if not present, generate it)
    vars.push(["type=[", string_typesig.join(","), "].join()"].join(""))
    vars.push("proc=CACHED[type]")
    code.push("var " + vars.join(","))
    
    code.push(["if(!proc){",
               "CACHED[type]=proc=compile([", typesig.join(","), "])}",
               "return proc(", proc_args.join(","), ")}"].join(""))
  
    if(proc.debug) {
      console.log("-----Generated thunk:\n" + code.join("\n") + "\n----------")
    }
    
    //Compile thunk
    var thunk = new Function("compile", code.join("\n"))
    return thunk(compile.bind(undefined, proc))
  }
  
  module.exports = createThunk
  
  },{"./compile.js":45}],47:[function(require,module,exports){
  module.exports = require('./lib/eql');
  
  },{"./lib/eql":48}],48:[function(require,module,exports){
  /*!
   * deep-eql
   * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependencies
   */
  
  var type = require('type-detect');
  
  /*!
   * Buffer.isBuffer browser shim
   */
  
  var Buffer;
  try { Buffer = require('buffer').Buffer; }
  catch(ex) {
    Buffer = {};
    Buffer.isBuffer = function() { return false; }
  }
  
  /*!
   * Primary Export
   */
  
  module.exports = deepEqual;
  
  /**
   * Assert super-strict (egal) equality between
   * two objects of any type.
   *
   * @param {Mixed} a
   * @param {Mixed} b
   * @param {Array} memoised (optional)
   * @return {Boolean} equal match
   */
  
  function deepEqual(a, b, m) {
    if (sameValue(a, b)) {
      return true;
    } else if ('date' === type(a)) {
      return dateEqual(a, b);
    } else if ('regexp' === type(a)) {
      return regexpEqual(a, b);
    } else if (Buffer.isBuffer(a)) {
      return bufferEqual(a, b);
    } else if ('arguments' === type(a)) {
      return argumentsEqual(a, b, m);
    } else if (!typeEqual(a, b)) {
      return false;
    } else if (('object' !== type(a) && 'object' !== type(b))
    && ('array' !== type(a) && 'array' !== type(b))) {
      return sameValue(a, b);
    } else {
      return objectEqual(a, b, m);
    }
  }
  
  /*!
   * Strict (egal) equality test. Ensures that NaN always
   * equals NaN and `-0` does not equal `+0`.
   *
   * @param {Mixed} a
   * @param {Mixed} b
   * @return {Boolean} equal match
   */
  
  function sameValue(a, b) {
    if (a === b) return a !== 0 || 1 / a === 1 / b;
    return a !== a && b !== b;
  }
  
  /*!
   * Compare the types of two given objects and
   * return if they are equal. Note that an Array
   * has a type of `array` (not `object`) and arguments
   * have a type of `arguments` (not `array`/`object`).
   *
   * @param {Mixed} a
   * @param {Mixed} b
   * @return {Boolean} result
   */
  
  function typeEqual(a, b) {
    return type(a) === type(b);
  }
  
  /*!
   * Compare two Date objects by asserting that
   * the time values are equal using `saveValue`.
   *
   * @param {Date} a
   * @param {Date} b
   * @return {Boolean} result
   */
  
  function dateEqual(a, b) {
    if ('date' !== type(b)) return false;
    return sameValue(a.getTime(), b.getTime());
  }
  
  /*!
   * Compare two regular expressions by converting them
   * to string and checking for `sameValue`.
   *
   * @param {RegExp} a
   * @param {RegExp} b
   * @return {Boolean} result
   */
  
  function regexpEqual(a, b) {
    if ('regexp' !== type(b)) return false;
    return sameValue(a.toString(), b.toString());
  }
  
  /*!
   * Assert deep equality of two `arguments` objects.
   * Unfortunately, these must be sliced to arrays
   * prior to test to ensure no bad behavior.
   *
   * @param {Arguments} a
   * @param {Arguments} b
   * @param {Array} memoize (optional)
   * @return {Boolean} result
   */
  
  function argumentsEqual(a, b, m) {
    if ('arguments' !== type(b)) return false;
    a = [].slice.call(a);
    b = [].slice.call(b);
    return deepEqual(a, b, m);
  }
  
  /*!
   * Get enumerable properties of a given object.
   *
   * @param {Object} a
   * @return {Array} property names
   */
  
  function enumerable(a) {
    var res = [];
    for (var key in a) res.push(key);
    return res;
  }
  
  /*!
   * Simple equality for flat iterable objects
   * such as Arrays or Node.js buffers.
   *
   * @param {Iterable} a
   * @param {Iterable} b
   * @return {Boolean} result
   */
  
  function iterableEqual(a, b) {
    if (a.length !==  b.length) return false;
  
    var i = 0;
    var match = true;
  
    for (; i < a.length; i++) {
      if (a[i] !== b[i]) {
        match = false;
        break;
      }
    }
  
    return match;
  }
  
  /*!
   * Extension to `iterableEqual` specifically
   * for Node.js Buffers.
   *
   * @param {Buffer} a
   * @param {Mixed} b
   * @return {Boolean} result
   */
  
  function bufferEqual(a, b) {
    if (!Buffer.isBuffer(b)) return false;
    return iterableEqual(a, b);
  }
  
  /*!
   * Block for `objectEqual` ensuring non-existing
   * values don't get in.
   *
   * @param {Mixed} object
   * @return {Boolean} result
   */
  
  function isValue(a) {
    return a !== null && a !== undefined;
  }
  
  /*!
   * Recursively check the equality of two objects.
   * Once basic sameness has been established it will
   * defer to `deepEqual` for each enumerable key
   * in the object.
   *
   * @param {Mixed} a
   * @param {Mixed} b
   * @return {Boolean} result
   */
  
  function objectEqual(a, b, m) {
    if (!isValue(a) || !isValue(b)) {
      return false;
    }
  
    if (a.prototype !== b.prototype) {
      return false;
    }
  
    var i;
    if (m) {
      for (i = 0; i < m.length; i++) {
        if ((m[i][0] === a && m[i][1] === b)
        ||  (m[i][0] === b && m[i][1] === a)) {
          return true;
        }
      }
    } else {
      m = [];
    }
  
    try {
      var ka = enumerable(a);
      var kb = enumerable(b);
    } catch (ex) {
      return false;
    }
  
    ka.sort();
    kb.sort();
  
    if (!iterableEqual(ka, kb)) {
      return false;
    }
  
    m.push([ a, b ]);
  
    var key;
    for (i = ka.length - 1; i >= 0; i--) {
      key = ka[i];
      if (!deepEqual(a[key], b[key], m)) {
        return false;
      }
    }
  
    return true;
  }
  
  },{"buffer":12,"type-detect":49}],49:[function(require,module,exports){
  module.exports = require('./lib/type');
  
  },{"./lib/type":50}],50:[function(require,module,exports){
  /*!
   * type-detect
   * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Primary Exports
   */
  
  var exports = module.exports = getType;
  
  /*!
   * Detectable javascript natives
   */
  
  var natives = {
      '[object Array]': 'array'
    , '[object RegExp]': 'regexp'
    , '[object Function]': 'function'
    , '[object Arguments]': 'arguments'
    , '[object Date]': 'date'
  };
  
  /**
   * ### typeOf (obj)
   *
   * Use several different techniques to determine
   * the type of object being tested.
   *
   *
   * @param {Mixed} object
   * @return {String} object type
   * @api public
   */
  
  function getType (obj) {
    var str = Object.prototype.toString.call(obj);
    if (natives[str]) return natives[str];
    if (obj === null) return 'null';
    if (obj === undefined) return 'undefined';
    if (obj === Object(obj)) return 'object';
    return typeof obj;
  }
  
  exports.Library = Library;
  
  /**
   * ### Library
   *
   * Create a repository for custom type detection.
   *
   * ```js
   * var lib = new type.Library;
   * ```
   *
   */
  
  function Library () {
    this.tests = {};
  }
  
  /**
   * #### .of (obj)
   *
   * Expose replacement `typeof` detection to the library.
   *
   * ```js
   * if ('string' === lib.of('hello world')) {
   *   // ...
   * }
   * ```
   *
   * @param {Mixed} object to test
   * @return {String} type
   */
  
  Library.prototype.of = getType;
  
  /**
   * #### .define (type, test)
   *
   * Add a test to for the `.test()` assertion.
   *
   * Can be defined as a regular expression:
   *
   * ```js
   * lib.define('int', /^[0-9]+$/);
   * ```
   *
   * ... or as a function:
   *
   * ```js
   * lib.define('bln', function (obj) {
   *   if ('boolean' === lib.of(obj)) return true;
   *   var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
   *   if ('string' === lib.of(obj)) obj = obj.toLowerCase();
   *   return !! ~blns.indexOf(obj);
   * });
   * ```
   *
   * @param {String} type
   * @param {RegExp|Function} test
   * @api public
   */
  
  Library.prototype.define = function (type, test) {
    if (arguments.length === 1) return this.tests[type];
    this.tests[type] = test;
    return this;
  };
  
  /**
   * #### .test (obj, test)
   *
   * Assert that an object is of type. Will first
   * check natives, and if that does not pass it will
   * use the user defined custom tests.
   *
   * ```js
   * assert(lib.test('1', 'int'));
   * assert(lib.test('yes', 'bln'));
   * ```
   *
   * @param {Mixed} object
   * @param {String} type
   * @return {Boolean} result
   * @api public
   */
  
  Library.prototype.test = function (obj, type) {
    if (type === getType(obj)) return true;
    var test = this.tests[type];
  
    if (test && 'regexp' === getType(test)) {
      return test.test(obj);
    } else if (test && 'function' === getType(test)) {
      return test(obj);
    } else {
      throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
    }
  };
  
  },{}],51:[function(require,module,exports){
  (function (Buffer){
  var BufferList = require("bl"),
      stream = require("readable-stream");
  
  var copy = function copy(o) {
    var r = {};
  
    for (var k in o) {
      if (Object.hasOwnProperty.call(o, k)) {
        r[k] = o[k];
      }
    }
  
    return r;
  };
  
  var Dissolve = module.exports = function Dissolve(options) {
    if (!(this instanceof Dissolve)) { return new Dissolve(); }
  
    if (!options) {
      options = {};
    }
  
    options.objectMode = true;
  
    stream.Transform.call(this, options);
  
    this.jobs = [];
    this.vars = Object.create(null);
    this.vars_list = [];
  
    this._buffer = new BufferList();
  };
  Dissolve.prototype = Object.create(stream.Transform.prototype, {constructor: {value: Dissolve}});
  
  Dissolve.prototype._job_down = function _job_down(job) {
    var tmp = this.vars;
    this.vars_list.push(tmp);
    this.vars = tmp[job.into] = Object.create(tmp);
  };
  
  Dissolve.prototype._job_up = function _job_up() {
    this.vars.__proto__ = null;
    this.vars = this.vars_list.pop();
  };
  
  Dissolve.prototype._transform = function _transform(input, encoding, done) {
    var offset = 0;
  
    this._buffer.append(input);
  
    while (this.jobs.length) {
      var job = this.jobs[0];
  
      if (job.type === "down") {
        this.jobs.shift();
  
        this._job_down(job);
  
        continue;
      }
  
      if (job.type === "up") {
        this.jobs.shift();
  
        this._job_up();
  
        continue;
      }
  
      if (job.type === "tap") {
        this.jobs.shift();
  
        var jobs = this.jobs.slice();
        this.jobs.splice(0);
        if (job.name) {
          this.jobs.push({type: "down", into: job.name});
          this.jobs.push({type: "tap", args: job.args, fn: job.fn});
          this.jobs.push({type: "up"});
        } else {
          job.fn.apply(this, job.args || []);
        }
        Array.prototype.splice.apply(this.jobs, [this.jobs.length, 0].concat(jobs));
  
        continue;
      }
  
      if (job.type === "loop") {
        if (job.finished) {
          this.jobs.shift();
          continue;
        }
  
        var jobs = this.jobs.slice();
        this.jobs.splice(0);
        if (job.name) {
          if (typeof this.vars[job.name] === "undefined") {
            this.vars[job.name] = [];
          }
  
          // private scope so _job doesn't get redefined later
          (function() {
            var _job = job;
  
            this.jobs.push({
              type: "tap",
              name: "__loop_temp",
              args: [job.finish],
              fn: job.fn,
            });
  
            this.jobs.push({
              type: "tap",
              fn: function() {
                if (!_job.cancelled) {
                  this.vars[_job.name].push(this.vars.__loop_temp);
                }
  
                delete this.vars.__loop_temp;
              },
            });
          }).call(this);
        } else {
          this.jobs.push({
            type: "tap",
            args: [job.finish],
            fn: job.fn,
          });
        }
        Array.prototype.splice.apply(this.jobs, [this.jobs.length, 0].concat(jobs));
  
        continue;
      }
  
      if (typeof job.length === "string") {
        job = copy(job);
        job.length = this.vars[job.length];
      }
  
      if (this._buffer.length - offset < job.length) {
        break;
      }
  
      if (job.type === "buffer") {
        this.vars[job.name] = new Buffer(job.length);
        this._buffer.copy(this.vars[job.name], 0, offset, offset + job.length);
  
        this.jobs.shift();
  
        offset += job.length;
  
        continue;
      }
  
      if (job.type === "string") {
        this.vars[job.name] = this._buffer.toString("utf8", offset, offset + job.length);
  
        this.jobs.shift();
  
        offset += job.length;
  
        continue;
      }
  
      switch (job.type) {
        case "int8le":  { this.vars[job.name] = this._buffer.readInt8(offset);  break; }
        case "uint8le": { this.vars[job.name] = this._buffer.readUInt8(offset); break; }
        case "int8be":  { this.vars[job.name] = this._buffer.readInt8(offset);  break; }
        case "uint8be": { this.vars[job.name] = this._buffer.readUInt8(offset); break; }
        case "int16le":  { this.vars[job.name] = this._buffer.readInt16LE(offset);  break; }
        case "uint16le": { this.vars[job.name] = this._buffer.readUInt16LE(offset); break; }
        case "int16be":  { this.vars[job.name] = this._buffer.readInt16BE(offset);  break; }
        case "uint16be": { this.vars[job.name] = this._buffer.readUInt16BE(offset); break; }
        case "int32le":  { this.vars[job.name] = this._buffer.readInt32LE(offset);  break; }
        case "uint32le": { this.vars[job.name] = this._buffer.readUInt32LE(offset); break; }
        case "int32be":  { this.vars[job.name] = this._buffer.readInt32BE(offset);  break; }
        case "uint32be": { this.vars[job.name] = this._buffer.readUInt32BE(offset); break; }
        case "int64le":  { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readInt32LE(offset + 4)) + ((this._buffer[offset + 4] & 0x80 === 0x80 ? 1 : -1) * this._buffer.readUInt32LE(offset)); break; }
        case "uint64le": { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readUInt32LE(offset + 4)) + this._buffer.readUInt32LE(offset); break; }
        case "int64be":  { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readInt32BE(offset)) + ((this._buffer[offset] & 0x80 === 0x80 ? 1 : -1) * this._buffer.readUInt32BE(offset + 4)); break; }
        case "uint64be": { this.vars[job.name] = (Math.pow(2, 32) * this._buffer.readUInt32BE(offset)) + this._buffer.readUInt32BE(offset + 4); break; }
        case "floatle":  { this.vars[job.name] = this._buffer.readFloatLE(offset);  break; }
        case "floatbe":  { this.vars[job.name] = this._buffer.readFloatBE(offset);  break; }
        case "doublele": { this.vars[job.name] = this._buffer.readDoubleLE(offset); break; }
        case "doublebe": { this.vars[job.name] = this._buffer.readDoubleBE(offset); break; }
        default: { return done(new Error("invalid job type")); }
      }
  
      this.jobs.shift();
  
      offset += job.length;
    }
  
    this._buffer.consume(offset);
  
    if (this.jobs.length === 0) {
      this.push(null);
    }
  
    return done();
  };
  
  [["float", 4], ["double", 8]].forEach(function(t) {
    ["", "le", "be"].forEach(function(e) {
      var id = [t[0], e].join(""),
          type = [t[0], e || "le"].join(""),
          length = t[1];
  
      Dissolve.prototype[id] = function(name) {
        this.jobs.push({
          type: type,
          length: length,
          name: name,
        });
  
        return this;
      };
    });
  });
  
  [8, 16, 32, 64].forEach(function(b) {
    ["", "u"].forEach(function(s) {
      ["", "le", "be"].forEach(function(e) {
        var id = [s, "int", b, e].join(""),
            type = [s, "int", b, e || "le"].join(""),
            length = b / 8;
  
        Dissolve.prototype[id] = function(name) {
          this.jobs.push({
            type: type,
            length: length,
            name: name,
          });
  
          return this;
        };
      });
    });
  });
  
  ["tap", "loop"].forEach(function(e) {
    Dissolve.prototype[e] = function(name, fn) {
      if (typeof name === "function") {
        fn = name;
        name = null;
      }
  
      var job = {
        type: e,
        name: name,
        fn: fn,
      };
  
      if (e === "loop") {
        job.finish = function(cancel) {
          job.finished = true;
          job.cancelled = !!cancel;
        };
      }
  
      this.jobs.push(job);
  
      return this;
    };
  });
  
  ["buffer", "string"].forEach(function(e) {
    Dissolve.prototype[e] = function(name, length) {
      this.jobs.push({
        type: e,
        name: name,
        length: length,
      });
  
      return this;
    };
  });
  
  }).call(this,require("buffer").Buffer)
  },{"bl":52,"buffer":12,"readable-stream":252}],52:[function(require,module,exports){
  (function (Buffer){
  var DuplexStream = require('readable-stream').Duplex
    , util         = require('util')
  
  function BufferList (callback) {
    if (!(this instanceof BufferList))
      return new BufferList(callback)
  
    this._bufs  = []
    this.length = 0
  
    if (typeof callback == 'function') {
      this._callback = callback
  
      var piper = function (err) {
        if (this._callback) {
          this._callback(err)
          this._callback = null
        }
      }.bind(this)
  
      this.on('pipe', function (src) {
        src.on('error', piper)
      })
      this.on('unpipe', function (src) {
        src.removeListener('error', piper)
      })
    }
    else if (Buffer.isBuffer(callback))
      this.append(callback)
    else if (Array.isArray(callback)) {
      callback.forEach(function (b) {
        Buffer.isBuffer(b) && this.append(b)
      }.bind(this))
    }
  
    DuplexStream.call(this)
  }
  
  util.inherits(BufferList, DuplexStream)
  
  BufferList.prototype._offset = function (offset) {
    var tot = 0, i = 0, _t
    for (; i < this._bufs.length; i++) {
      _t = tot + this._bufs[i].length
      if (offset < _t)
        return [ i, offset - tot ]
      tot = _t
    }
  }
  
  BufferList.prototype.append = function (buf) {
    this._bufs.push(Buffer.isBuffer(buf) ? buf : new Buffer(buf))
    this.length += buf.length
    return this
  }
  
  BufferList.prototype._write = function (buf, encoding, callback) {
    this.append(buf)
    if (callback)
      callback()
  }
  
  BufferList.prototype._read = function (size) {
    if (!this.length)
      return this.push(null)
    size = Math.min(size, this.length)
    this.push(this.slice(0, size))
    this.consume(size)
  }
  
  BufferList.prototype.end = function (chunk) {
    DuplexStream.prototype.end.call(this, chunk)
  
    if (this._callback) {
      this._callback(null, this.slice())
      this._callback = null
    }
  }
  
  BufferList.prototype.get = function (index) {
    return this.slice(index, index + 1)[0]
  }
  
  BufferList.prototype.slice = function (start, end) {
    return this.copy(null, 0, start, end)
  }
  
  BufferList.prototype.copy = function (dst, dstStart, srcStart, srcEnd) {
    if (typeof srcStart != 'number' || srcStart < 0)
      srcStart = 0
    if (typeof srcEnd != 'number' || srcEnd > this.length)
      srcEnd = this.length
    if (srcStart >= this.length)
      return dst || new Buffer(0)
    if (srcEnd <= 0)
      return dst || new Buffer(0)
  
    var copy   = !!dst
      , off    = this._offset(srcStart)
      , len    = srcEnd - srcStart
      , bytes  = len
      , bufoff = (copy && dstStart) || 0
      , start  = off[1]
      , l
      , i
  
    // copy/slice everything
    if (srcStart === 0 && srcEnd == this.length) {
      if (!copy) // slice, just return a full concat
        return Buffer.concat(this._bufs)
  
      // copy, need to copy individual buffers
      for (i = 0; i < this._bufs.length; i++) {
        this._bufs[i].copy(dst, bufoff)
        bufoff += this._bufs[i].length
      }
  
      return dst
    }
  
    // easy, cheap case where it's a subset of one of the buffers
    if (bytes <= this._bufs[off[0]].length - start) {
      return copy
        ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes)
        : this._bufs[off[0]].slice(start, start + bytes)
    }
  
    if (!copy) // a slice, we need something to copy in to
      dst = new Buffer(len)
  
    for (i = off[0]; i < this._bufs.length; i++) {
      l = this._bufs[i].length - start
  
      if (bytes > l) {
        this._bufs[i].copy(dst, bufoff, start)
      } else {
        this._bufs[i].copy(dst, bufoff, start, start + bytes)
        break
      }
  
      bufoff += l
      bytes -= l
  
      if (start)
        start = 0
    }
  
    return dst
  }
  
  BufferList.prototype.toString = function (encoding, start, end) {
    return this.slice(start, end).toString(encoding)
  }
  
  BufferList.prototype.consume = function (bytes) {
    while (this._bufs.length) {
      if (bytes > this._bufs[0].length) {
        bytes -= this._bufs[0].length
        this.length -= this._bufs[0].length
        this._bufs.shift()
      } else {
        this._bufs[0] = this._bufs[0].slice(bytes)
        this.length -= bytes
        break
      }
    }
    return this
  }
  
  BufferList.prototype.duplicate = function () {
    var i = 0
      , copy = new BufferList()
  
    for (; i < this._bufs.length; i++)
      copy.append(this._bufs[i])
  
    return copy
  }
  
  ;(function () {
    var methods = {
        'readDoubleBE' : 8
      , 'readDoubleLE' : 8
      , 'readFloatBE'  : 4
      , 'readFloatLE'  : 4
      , 'readInt32BE'  : 4
      , 'readInt32LE'  : 4
      , 'readUInt32BE' : 4
      , 'readUInt32LE' : 4
      , 'readInt16BE'  : 2
      , 'readInt16LE'  : 2
      , 'readUInt16BE' : 2
      , 'readUInt16LE' : 2
      , 'readInt8'     : 1
      , 'readUInt8'    : 1
    }
  
    for (var m in methods) {
      (function (m) {
        BufferList.prototype[m] = function (offset) {
          return this.slice(offset, offset + methods[m])[m](0)
        }
      }(m))
    }
  }())
  
  module.exports = BufferList
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":12,"readable-stream":258,"util":269}],53:[function(require,module,exports){
  module.exports = function(dtype) {
    switch (dtype) {
      case 'int8':
        return Int8Array
      case 'int16':
        return Int16Array
      case 'int32':
        return Int32Array
      case 'uint8':
        return Uint8Array
      case 'uint16':
        return Uint16Array
      case 'uint32':
        return Uint32Array
      case 'float32':
        return Float32Array
      case 'float64':
        return Float64Array
      case 'array':
        return Array
    }
  }
  },{}],54:[function(require,module,exports){
  "use strict"
  
  function dupe_array(count, value, i) {
    var c = count[i]|0
    if(c <= 0) {
      return []
    }
    var result = new Array(c), j
    if(i === count.length-1) {
      for(j=0; j<c; ++j) {
        result[j] = value
      }
    } else {
      for(j=0; j<c; ++j) {
        result[j] = dupe_array(count, value, i+1)
      }
    }
    return result
  }
  
  function dupe_number(count, value) {
    var result, i
    result = new Array(count)
    for(i=0; i<count; ++i) {
      result[i] = value
    }
    return result
  }
  
  function dupe(count, value) {
    if(typeof value === "undefined") {
      value = 0
    }
    switch(typeof count) {
      case "number":
        if(count > 0) {
          return dupe_number(count|0, value)
        }
      break
      case "object":
        if(typeof (count.length) === "number") {
          return dupe_array(count, value, 0)
        }
      break
    }
    return []
  }
  
  module.exports = dupe
  },{}],55:[function(require,module,exports){
  module.exports = getSize
  
  function getSize(element) {
    // Handle cases where the element is not already
    // attached to the DOM by briefly appending it
    // to document.body, and removing it again later.
    if (element === window || element === document.body) {
      return [window.innerWidth, window.innerHeight]
    }
  
    if (!element.parentNode) {
      var temporary = true
      document.body.appendChild(element)
    }
  
    var bounds = element.getBoundingClientRect()
    var styles = getComputedStyle(element)
    var height = (bounds.height|0)
      + parse(styles.getPropertyValue('margin-top'))
      + parse(styles.getPropertyValue('margin-bottom'))
    var width  = (bounds.width|0)
      + parse(styles.getPropertyValue('margin-left'))
      + parse(styles.getPropertyValue('margin-right'))
  
    if (temporary) {
      document.body.removeChild(element)
    }
  
    return [width, height]
  }
  
  function parse(prop) {
    return parseFloat(prop) || 0
  }
  
  },{}],56:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  function EventEmitter() {
    this._events = this._events || {};
    this._maxListeners = this._maxListeners || undefined;
  }
  module.exports = EventEmitter;
  
  // Backwards-compat with node 0.10.x
  EventEmitter.EventEmitter = EventEmitter;
  
  EventEmitter.prototype._events = undefined;
  EventEmitter.prototype._maxListeners = undefined;
  
  // By default EventEmitters will print a warning if more than 10 listeners are
  // added to it. This is a useful default which helps finding memory leaks.
  EventEmitter.defaultMaxListeners = 10;
  
  // Obviously not all Emitters should be limited to 10. This function allows
  // that to be increased. Set to zero for unlimited.
  EventEmitter.prototype.setMaxListeners = function(n) {
    if (!isNumber(n) || n < 0 || isNaN(n))
      throw TypeError('n must be a positive number');
    this._maxListeners = n;
    return this;
  };
  
  EventEmitter.prototype.emit = function(type) {
    var er, handler, len, args, i, listeners;
  
    if (!this._events)
      this._events = {};
  
    // If there is no 'error' event listener then throw.
    if (type === 'error') {
      if (!this._events.error ||
          (isObject(this._events.error) && !this._events.error.length)) {
        er = arguments[1];
        if (er instanceof Error) {
          throw er; // Unhandled 'error' event
        }
        throw TypeError('Uncaught, unspecified "error" event.');
      }
    }
  
    handler = this._events[type];
  
    if (isUndefined(handler))
      return false;
  
    if (isFunction(handler)) {
      switch (arguments.length) {
        // fast cases
        case 1:
          handler.call(this);
          break;
        case 2:
          handler.call(this, arguments[1]);
          break;
        case 3:
          handler.call(this, arguments[1], arguments[2]);
          break;
        // slower
        default:
          len = arguments.length;
          args = new Array(len - 1);
          for (i = 1; i < len; i++)
            args[i - 1] = arguments[i];
          handler.apply(this, args);
      }
    } else if (isObject(handler)) {
      len = arguments.length;
      args = new Array(len - 1);
      for (i = 1; i < len; i++)
        args[i - 1] = arguments[i];
  
      listeners = handler.slice();
      len = listeners.length;
      for (i = 0; i < len; i++)
        listeners[i].apply(this, args);
    }
  
    return true;
  };
  
  EventEmitter.prototype.addListener = function(type, listener) {
    var m;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events)
      this._events = {};
  
    // To avoid recursion in the case that type === "newListener"! Before
    // adding it to the listeners, first emit "newListener".
    if (this._events.newListener)
      this.emit('newListener', type,
                isFunction(listener.listener) ?
                listener.listener : listener);
  
    if (!this._events[type])
      // Optimize the case of one listener. Don't need the extra array object.
      this._events[type] = listener;
    else if (isObject(this._events[type]))
      // If we've already got an array, just append.
      this._events[type].push(listener);
    else
      // Adding the second element, need to change to array.
      this._events[type] = [this._events[type], listener];
  
    // Check for listener leak
    if (isObject(this._events[type]) && !this._events[type].warned) {
      var m;
      if (!isUndefined(this._maxListeners)) {
        m = this._maxListeners;
      } else {
        m = EventEmitter.defaultMaxListeners;
      }
  
      if (m && m > 0 && this._events[type].length > m) {
        this._events[type].warned = true;
        console.error('(node) warning: possible EventEmitter memory ' +
                      'leak detected. %d listeners added. ' +
                      'Use emitter.setMaxListeners() to increase limit.',
                      this._events[type].length);
        if (typeof console.trace === 'function') {
          // not supported in IE 10
          console.trace();
        }
      }
    }
  
    return this;
  };
  
  EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  
  EventEmitter.prototype.once = function(type, listener) {
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    var fired = false;
  
    function g() {
      this.removeListener(type, g);
  
      if (!fired) {
        fired = true;
        listener.apply(this, arguments);
      }
    }
  
    g.listener = listener;
    this.on(type, g);
  
    return this;
  };
  
  // emits a 'removeListener' event iff the listener was removed
  EventEmitter.prototype.removeListener = function(type, listener) {
    var list, position, length, i;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events || !this._events[type])
      return this;
  
    list = this._events[type];
    length = list.length;
    position = -1;
  
    if (list === listener ||
        (isFunction(list.listener) && list.listener === listener)) {
      delete this._events[type];
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
  
    } else if (isObject(list)) {
      for (i = length; i-- > 0;) {
        if (list[i] === listener ||
            (list[i].listener && list[i].listener === listener)) {
          position = i;
          break;
        }
      }
  
      if (position < 0)
        return this;
  
      if (list.length === 1) {
        list.length = 0;
        delete this._events[type];
      } else {
        list.splice(position, 1);
      }
  
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
    }
  
    return this;
  };
  
  EventEmitter.prototype.removeAllListeners = function(type) {
    var key, listeners;
  
    if (!this._events)
      return this;
  
    // not listening for removeListener, no need to emit
    if (!this._events.removeListener) {
      if (arguments.length === 0)
        this._events = {};
      else if (this._events[type])
        delete this._events[type];
      return this;
    }
  
    // emit removeListener for all listeners on all events
    if (arguments.length === 0) {
      for (key in this._events) {
        if (key === 'removeListener') continue;
        this.removeAllListeners(key);
      }
      this.removeAllListeners('removeListener');
      this._events = {};
      return this;
    }
  
    listeners = this._events[type];
  
    if (isFunction(listeners)) {
      this.removeListener(type, listeners);
    } else {
      // LIFO order
      while (listeners.length)
        this.removeListener(type, listeners[listeners.length - 1]);
    }
    delete this._events[type];
  
    return this;
  };
  
  EventEmitter.prototype.listeners = function(type) {
    var ret;
    if (!this._events || !this._events[type])
      ret = [];
    else if (isFunction(this._events[type]))
      ret = [this._events[type]];
    else
      ret = this._events[type].slice();
    return ret;
  };
  
  EventEmitter.listenerCount = function(emitter, type) {
    var ret;
    if (!emitter._events || !emitter._events[type])
      ret = 0;
    else if (isFunction(emitter._events[type]))
      ret = 1;
    else
      ret = emitter._events[type].length;
    return ret;
  };
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  
  },{}],57:[function(require,module,exports){
  var isFunction = require('is-function')
  
  module.exports = forEach
  
  var toString = Object.prototype.toString
  var hasOwnProperty = Object.prototype.hasOwnProperty
  
  function forEach(list, iterator, context) {
      if (!isFunction(iterator)) {
          throw new TypeError('iterator must be a function')
      }
  
      if (arguments.length < 3) {
          context = this
      }
      
      if (toString.call(list) === '[object Array]')
          forEachArray(list, iterator, context)
      else if (typeof list === 'string')
          forEachString(list, iterator, context)
      else
          forEachObject(list, iterator, context)
  }
  
  function forEachArray(array, iterator, context) {
      for (var i = 0, len = array.length; i < len; i++) {
          if (hasOwnProperty.call(array, i)) {
              iterator.call(context, array[i], i, array)
          }
      }
  }
  
  function forEachString(string, iterator, context) {
      for (var i = 0, len = string.length; i < len; i++) {
          // no such thing as a sparse string.
          iterator.call(context, string.charAt(i), i, string)
      }
  }
  
  function forEachObject(object, iterator, context) {
      for (var k in object) {
          if (hasOwnProperty.call(object, k)) {
              iterator.call(context, object[k], k, object)
          }
      }
  }
  
  },{"is-function":198}],58:[function(require,module,exports){
  module.exports = {
    axes: [
        '<axis-left-x>'
      , '<axis-left-y>'
      , '<axis-right-x>'
      , '<axis-right-y>'
    ],
    buttons: [
        '<action 1>'
      , '<action 2>'
      , '<action 3>'
      , '<action 4>'
      , '<shoulder-top-left>'
      , '<shoulder-top-right>'
      , '<shoulder-bottom-left>'
      , '<shoulder-bottom-right>'
      , '<meta 1>'
      , '<meta 2>'
      , '<stick-button 1>'
      , '<stick-button 2>'
      , '<up>'
      , '<down>'
      , '<left>'
      , '<right>'
    ]
  }
  
  },{}],59:[function(require,module,exports){
  "use strict"
  
  var pool = require("typedarray-pool")
  var ops = require("ndarray-ops")
  var ndarray = require("ndarray")
  
  var SUPPORTED_TYPES = [
    "uint8",
    "uint8_clamped",
    "uint16",
    "uint32",
    "int8",
    "int16",
    "int32",
    "float32" ]
  
  function GLBuffer(gl, type, handle, length, usage) {
    this.gl = gl
    this.type = type
    this.handle = handle
    this.length = length
    this.usage = usage
  }
  
  var proto = GLBuffer.prototype
  
  proto.bind = function() {
    this.gl.bindBuffer(this.type, this.handle)
  }
  
  proto.unbind = function() {
    this.gl.bindBuffer(this.type, null)
  }
  
  proto.dispose = function() {
    this.gl.deleteBuffer(this.handle)
  }
  
  function updateTypeArray(gl, type, len, usage, data, offset) {
    var dataLen = data.length * data.BYTES_PER_ELEMENT
    if(offset < 0) {
      gl.bufferData(type, data, usage)
      return dataLen
    }
    if(dataLen + offset > len) {
      throw new Error("gl-buffer in node_modules: If resizing buffer, must not specify offset; dataLen ",dataLen," offset",offset," len",len)
    }
    gl.bufferSubData(type, offset, data)
    return len
  }
  
  function makeScratchTypeArray(array, dtype) {
    var res = pool.malloc(array.length, dtype)
    var n = array.length
    for(var i=0; i<n; ++i) {
      res[i] = array[i]
    }
    return res
  }
  
  function isPacked(shape, stride) {
    var n = 1
    for(var i=stride.length-1; i>=0; --i) {
      if(stride[i] !== n) {
        return false
      }
      n *= shape[i]
    }
    return true
  }
  
  proto.update = function(array, offset) {
    if(typeof offset !== "number") {
      offset = -1
    }
    this.bind()
    if(typeof array === "object" && typeof array.shape !== "undefined") { //ndarray
      var dtype = array.dtype
      if(SUPPORTED_TYPES.indexOf(dtype) < 0) {
        dtype = "float32"
      }
      if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) {
        var ext = gl.getExtension('OES_element_index_uint')
        if(ext && dtype !== "uint16") {
          dtype = "uint32"
        } else {
          dtype = "uint16"
        }
      }
      if(dtype === array.dtype && isPacked(array.shape, array.stride)) {
        if(array.offset === 0 && array.data.length === array.shape[0]) {
          this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data, offset)
        } else {
          this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data.subarray(array.offset, array.shape[0]), offset)
        }
      } else {
        var tmp = pool.malloc(array.size, dtype)
        var ndt = ndarray(tmp, array.shape)
        ops.assign(ndt, array)
        if(offset < 0) {
          this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp, offset)
        } else {
          this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp.subarray(0, array.size), offset)
        }
        pool.free(tmp)
      }
    } else if(Array.isArray(array)) { //Vanilla array
      var t
      if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) {
        t = makeScratchTypeArray(array, "uint16")
      } else {
        t = makeScratchTypeArray(array, "float32")
      }
      if(offset < 0) {
        this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t, offset)
      } else {
        this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t.subarray(0, array.length), offset)
      }
      pool.free(t)
    } else if(typeof array === "object" && typeof array.length === "number") { //Typed array
      this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array, offset)
    } else if(typeof array === "number" || array === undefined) { //Number/default
      if(offset >= 0) {
        throw new Error("gl-buffer: Cannot specify offset when resizing buffer")
      }
      array = array | 0
      if(array <= 0) {
        array = 1
      }
      this.gl.bufferData(this.type, array|0, this.usage)
      this.length = array
    } else { //Error, case should not happen
      throw new Error("gl-buffer: Invalid data type")
    }
  }
  
  function createBuffer(gl, data, type, usage) {
    type = type || gl.ARRAY_BUFFER
    usage = usage || gl.DYNAMIC_DRAW
    if(type !== gl.ARRAY_BUFFER && type !== gl.ELEMENT_ARRAY_BUFFER) {
      throw new Error("gl-buffer: Invalid type for webgl buffer, must be either gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER")
    }
    if(usage !== gl.DYNAMIC_DRAW && usage !== gl.STATIC_DRAW && usage !== gl.STREAM_DRAW) {
      throw new Error("gl-buffer: Invalid usage for buffer, must be either gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW")
    }
    var handle = gl.createBuffer()
    var result = new GLBuffer(gl, type, handle, 0, usage)
    result.update(data)
    return result
  }
  
  module.exports = createBuffer
  
  },{"ndarray":204,"ndarray-ops":203,"typedarray-pool":265}],60:[function(require,module,exports){
  exports.color = function(color) {
    return array(color, [0, 0, 0, 1])
  }
  
  exports.depth = function(depth) {
    return number(depth, 1)
  }
  
  exports.stencil = function(stencil) {
    return number(stencil, false)
  }
  
  function number(n, def) {
    if (n === false) return false
    if (typeof n === 'undefined') return def
    return n + 0
  }
  
  function array(a, def) {
    if (a === false) return false
    if (Array.isArray(a)) return a || def
    return def
  }
  
  },{}],61:[function(require,module,exports){
  var defaults = require('./defaults')
  
  module.exports = clear
  
  function clear(opts) {
    opts = opts || {}
  
    var color = defaults.color(opts.color)
    Object.defineProperty(clear, 'color', {
      get: function() { return color },
      set: function(value) {
        return color = defaults.color(value)
      }
    })
  
    var depth = defaults.depth(opts.depth)
    Object.defineProperty(clear, 'depth', {
      get: function() { return depth },
      set: function(value) {
        return depth = defaults.depth(value)
      }
    })
  
    var stencil = defaults.stencil(opts.stencil)
    Object.defineProperty(clear, 'stencil', {
      get: function() { return stencil },
      set: function(value) {
        return stencil = defaults.stencil(value)
      }
    })
  
    return clear
  
    function clear(gl) {
      var flags = 0
  
      if (color !== false) {
        gl.clearColor(color[0], color[1], color[2], color[3])
        flags |= gl.COLOR_BUFFER_BIT
      }
      if (depth !== false) {
        gl.clearDepth(depth)
        flags |= gl.DEPTH_BUFFER_BIT
      }
      if (stencil !== false) {
        gl.clearStencil(stencil)
        flags |= gl.STENCIL_BUFFER_BIT
      }
  
      gl.clear(flags)
  
      return gl
    }
  }
  
  },{"./defaults":60}],62:[function(require,module,exports){
  module.exports = {
    0: 'NONE',
    1: 'ONE',
    2: 'LINE_LOOP',
    3: 'LINE_STRIP',
    4: 'TRIANGLES',
    5: 'TRIANGLE_STRIP',
    6: 'TRIANGLE_FAN',
    256: 'DEPTH_BUFFER_BIT',
    512: 'NEVER',
    513: 'LESS',
    514: 'EQUAL',
    515: 'LEQUAL',
    516: 'GREATER',
    517: 'NOTEQUAL',
    518: 'GEQUAL',
    519: 'ALWAYS',
    768: 'SRC_COLOR',
    769: 'ONE_MINUS_SRC_COLOR',
    770: 'SRC_ALPHA',
    771: 'ONE_MINUS_SRC_ALPHA',
    772: 'DST_ALPHA',
    773: 'ONE_MINUS_DST_ALPHA',
    774: 'DST_COLOR',
    775: 'ONE_MINUS_DST_COLOR',
    776: 'SRC_ALPHA_SATURATE',
    1024: 'STENCIL_BUFFER_BIT',
    1028: 'FRONT',
    1029: 'BACK',
    1032: 'FRONT_AND_BACK',
    1280: 'INVALID_ENUM',
    1281: 'INVALID_VALUE',
    1282: 'INVALID_OPERATION',
    1285: 'OUT_OF_MEMORY',
    1286: 'INVALID_FRAMEBUFFER_OPERATION',
    2304: 'CW',
    2305: 'CCW',
    2849: 'LINE_WIDTH',
    2884: 'CULL_FACE',
    2885: 'CULL_FACE_MODE',
    2886: 'FRONT_FACE',
    2928: 'DEPTH_RANGE',
    2929: 'DEPTH_TEST',
    2930: 'DEPTH_WRITEMASK',
    2931: 'DEPTH_CLEAR_VALUE',
    2932: 'DEPTH_FUNC',
    2960: 'STENCIL_TEST',
    2961: 'STENCIL_CLEAR_VALUE',
    2962: 'STENCIL_FUNC',
    2963: 'STENCIL_VALUE_MASK',
    2964: 'STENCIL_FAIL',
    2965: 'STENCIL_PASS_DEPTH_FAIL',
    2966: 'STENCIL_PASS_DEPTH_PASS',
    2967: 'STENCIL_REF',
    2968: 'STENCIL_WRITEMASK',
    2978: 'VIEWPORT',
    3024: 'DITHER',
    3042: 'BLEND',
    3088: 'SCISSOR_BOX',
    3089: 'SCISSOR_TEST',
    3106: 'COLOR_CLEAR_VALUE',
    3107: 'COLOR_WRITEMASK',
    3317: 'UNPACK_ALIGNMENT',
    3333: 'PACK_ALIGNMENT',
    3379: 'MAX_TEXTURE_SIZE',
    3386: 'MAX_VIEWPORT_DIMS',
    3408: 'SUBPIXEL_BITS',
    3410: 'RED_BITS',
    3411: 'GREEN_BITS',
    3412: 'BLUE_BITS',
    3413: 'ALPHA_BITS',
    3414: 'DEPTH_BITS',
    3415: 'STENCIL_BITS',
    3553: 'TEXTURE_2D',
    4352: 'DONT_CARE',
    4353: 'FASTEST',
    4354: 'NICEST',
    5120: 'BYTE',
    5121: 'UNSIGNED_BYTE',
    5122: 'SHORT',
    5123: 'UNSIGNED_SHORT',
    5124: 'INT',
    5125: 'UNSIGNED_INT',
    5126: 'FLOAT',
    5386: 'INVERT',
    5890: 'TEXTURE',
    6401: 'STENCIL_INDEX',
    6402: 'DEPTH_COMPONENT',
    6406: 'ALPHA',
    6407: 'RGB',
    6408: 'RGBA',
    6409: 'LUMINANCE',
    6410: 'LUMINANCE_ALPHA',
    7680: 'KEEP',
    7681: 'REPLACE',
    7682: 'INCR',
    7683: 'DECR',
    7936: 'VENDOR',
    7937: 'RENDERER',
    7938: 'VERSION',
    9728: 'NEAREST',
    9729: 'LINEAR',
    9984: 'NEAREST_MIPMAP_NEAREST',
    9985: 'LINEAR_MIPMAP_NEAREST',
    9986: 'NEAREST_MIPMAP_LINEAR',
    9987: 'LINEAR_MIPMAP_LINEAR',
    10240: 'TEXTURE_MAG_FILTER',
    10241: 'TEXTURE_MIN_FILTER',
    10242: 'TEXTURE_WRAP_S',
    10243: 'TEXTURE_WRAP_T',
    10497: 'REPEAT',
    10752: 'POLYGON_OFFSET_UNITS',
    16384: 'COLOR_BUFFER_BIT',
    32769: 'CONSTANT_COLOR',
    32770: 'ONE_MINUS_CONSTANT_COLOR',
    32771: 'CONSTANT_ALPHA',
    32772: 'ONE_MINUS_CONSTANT_ALPHA',
    32773: 'BLEND_COLOR',
    32774: 'FUNC_ADD',
    32777: 'BLEND_EQUATION_RGB',
    32778: 'FUNC_SUBTRACT',
    32779: 'FUNC_REVERSE_SUBTRACT',
    32819: 'UNSIGNED_SHORT_4_4_4_4',
    32820: 'UNSIGNED_SHORT_5_5_5_1',
    32823: 'POLYGON_OFFSET_FILL',
    32824: 'POLYGON_OFFSET_FACTOR',
    32854: 'RGBA4',
    32855: 'RGB5_A1',
    32873: 'TEXTURE_BINDING_2D',
    32926: 'SAMPLE_ALPHA_TO_COVERAGE',
    32928: 'SAMPLE_COVERAGE',
    32936: 'SAMPLE_BUFFERS',
    32937: 'SAMPLES',
    32938: 'SAMPLE_COVERAGE_VALUE',
    32939: 'SAMPLE_COVERAGE_INVERT',
    32968: 'BLEND_DST_RGB',
    32969: 'BLEND_SRC_RGB',
    32970: 'BLEND_DST_ALPHA',
    32971: 'BLEND_SRC_ALPHA',
    33071: 'CLAMP_TO_EDGE',
    33170: 'GENERATE_MIPMAP_HINT',
    33189: 'DEPTH_COMPONENT16',
    33306: 'DEPTH_STENCIL_ATTACHMENT',
    33635: 'UNSIGNED_SHORT_5_6_5',
    33648: 'MIRRORED_REPEAT',
    33901: 'ALIASED_POINT_SIZE_RANGE',
    33902: 'ALIASED_LINE_WIDTH_RANGE',
    33984: 'TEXTURE0',
    33985: 'TEXTURE1',
    33986: 'TEXTURE2',
    33987: 'TEXTURE3',
    33988: 'TEXTURE4',
    33989: 'TEXTURE5',
    33990: 'TEXTURE6',
    33991: 'TEXTURE7',
    33992: 'TEXTURE8',
    33993: 'TEXTURE9',
    33994: 'TEXTURE10',
    33995: 'TEXTURE11',
    33996: 'TEXTURE12',
    33997: 'TEXTURE13',
    33998: 'TEXTURE14',
    33999: 'TEXTURE15',
    34000: 'TEXTURE16',
    34001: 'TEXTURE17',
    34002: 'TEXTURE18',
    34003: 'TEXTURE19',
    34004: 'TEXTURE20',
    34005: 'TEXTURE21',
    34006: 'TEXTURE22',
    34007: 'TEXTURE23',
    34008: 'TEXTURE24',
    34009: 'TEXTURE25',
    34010: 'TEXTURE26',
    34011: 'TEXTURE27',
    34012: 'TEXTURE28',
    34013: 'TEXTURE29',
    34014: 'TEXTURE30',
    34015: 'TEXTURE31',
    34016: 'ACTIVE_TEXTURE',
    34024: 'MAX_RENDERBUFFER_SIZE',
    34041: 'DEPTH_STENCIL',
    34055: 'INCR_WRAP',
    34056: 'DECR_WRAP',
    34067: 'TEXTURE_CUBE_MAP',
    34068: 'TEXTURE_BINDING_CUBE_MAP',
    34069: 'TEXTURE_CUBE_MAP_POSITIVE_X',
    34070: 'TEXTURE_CUBE_MAP_NEGATIVE_X',
    34071: 'TEXTURE_CUBE_MAP_POSITIVE_Y',
    34072: 'TEXTURE_CUBE_MAP_NEGATIVE_Y',
    34073: 'TEXTURE_CUBE_MAP_POSITIVE_Z',
    34074: 'TEXTURE_CUBE_MAP_NEGATIVE_Z',
    34076: 'MAX_CUBE_MAP_TEXTURE_SIZE',
    34338: 'VERTEX_ATTRIB_ARRAY_ENABLED',
    34339: 'VERTEX_ATTRIB_ARRAY_SIZE',
    34340: 'VERTEX_ATTRIB_ARRAY_STRIDE',
    34341: 'VERTEX_ATTRIB_ARRAY_TYPE',
    34342: 'CURRENT_VERTEX_ATTRIB',
    34373: 'VERTEX_ATTRIB_ARRAY_POINTER',
    34466: 'NUM_COMPRESSED_TEXTURE_FORMATS',
    34467: 'COMPRESSED_TEXTURE_FORMATS',
    34660: 'BUFFER_SIZE',
    34661: 'BUFFER_USAGE',
    34816: 'STENCIL_BACK_FUNC',
    34817: 'STENCIL_BACK_FAIL',
    34818: 'STENCIL_BACK_PASS_DEPTH_FAIL',
    34819: 'STENCIL_BACK_PASS_DEPTH_PASS',
    34877: 'BLEND_EQUATION_ALPHA',
    34921: 'MAX_VERTEX_ATTRIBS',
    34922: 'VERTEX_ATTRIB_ARRAY_NORMALIZED',
    34930: 'MAX_TEXTURE_IMAGE_UNITS',
    34962: 'ARRAY_BUFFER',
    34963: 'ELEMENT_ARRAY_BUFFER',
    34964: 'ARRAY_BUFFER_BINDING',
    34965: 'ELEMENT_ARRAY_BUFFER_BINDING',
    34975: 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING',
    35040: 'STREAM_DRAW',
    35044: 'STATIC_DRAW',
    35048: 'DYNAMIC_DRAW',
    35632: 'FRAGMENT_SHADER',
    35633: 'VERTEX_SHADER',
    35660: 'MAX_VERTEX_TEXTURE_IMAGE_UNITS',
    35661: 'MAX_COMBINED_TEXTURE_IMAGE_UNITS',
    35663: 'SHADER_TYPE',
    35664: 'FLOAT_VEC2',
    35665: 'FLOAT_VEC3',
    35666: 'FLOAT_VEC4',
    35667: 'INT_VEC2',
    35668: 'INT_VEC3',
    35669: 'INT_VEC4',
    35670: 'BOOL',
    35671: 'BOOL_VEC2',
    35672: 'BOOL_VEC3',
    35673: 'BOOL_VEC4',
    35674: 'FLOAT_MAT2',
    35675: 'FLOAT_MAT3',
    35676: 'FLOAT_MAT4',
    35678: 'SAMPLER_2D',
    35680: 'SAMPLER_CUBE',
    35712: 'DELETE_STATUS',
    35713: 'COMPILE_STATUS',
    35714: 'LINK_STATUS',
    35715: 'VALIDATE_STATUS',
    35716: 'INFO_LOG_LENGTH',
    35717: 'ATTACHED_SHADERS',
    35718: 'ACTIVE_UNIFORMS',
    35719: 'ACTIVE_UNIFORM_MAX_LENGTH',
    35720: 'SHADER_SOURCE_LENGTH',
    35721: 'ACTIVE_ATTRIBUTES',
    35722: 'ACTIVE_ATTRIBUTE_MAX_LENGTH',
    35724: 'SHADING_LANGUAGE_VERSION',
    35725: 'CURRENT_PROGRAM',
    36003: 'STENCIL_BACK_REF',
    36004: 'STENCIL_BACK_VALUE_MASK',
    36005: 'STENCIL_BACK_WRITEMASK',
    36006: 'FRAMEBUFFER_BINDING',
    36007: 'RENDERBUFFER_BINDING',
    36048: 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE',
    36049: 'FRAMEBUFFER_ATTACHMENT_OBJECT_NAME',
    36050: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL',
    36051: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE',
    36053: 'FRAMEBUFFER_COMPLETE',
    36054: 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT',
    36055: 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT',
    36057: 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS',
    36061: 'FRAMEBUFFER_UNSUPPORTED',
    36064: 'COLOR_ATTACHMENT0',
    36096: 'DEPTH_ATTACHMENT',
    36128: 'STENCIL_ATTACHMENT',
    36160: 'FRAMEBUFFER',
    36161: 'RENDERBUFFER',
    36162: 'RENDERBUFFER_WIDTH',
    36163: 'RENDERBUFFER_HEIGHT',
    36164: 'RENDERBUFFER_INTERNAL_FORMAT',
    36168: 'STENCIL_INDEX8',
    36176: 'RENDERBUFFER_RED_SIZE',
    36177: 'RENDERBUFFER_GREEN_SIZE',
    36178: 'RENDERBUFFER_BLUE_SIZE',
    36179: 'RENDERBUFFER_ALPHA_SIZE',
    36180: 'RENDERBUFFER_DEPTH_SIZE',
    36181: 'RENDERBUFFER_STENCIL_SIZE',
    36194: 'RGB565',
    36336: 'LOW_FLOAT',
    36337: 'MEDIUM_FLOAT',
    36338: 'HIGH_FLOAT',
    36339: 'LOW_INT',
    36340: 'MEDIUM_INT',
    36341: 'HIGH_INT',
    36346: 'SHADER_COMPILER',
    36347: 'MAX_VERTEX_UNIFORM_VECTORS',
    36348: 'MAX_VARYING_VECTORS',
    36349: 'MAX_FRAGMENT_UNIFORM_VECTORS',
    37440: 'UNPACK_FLIP_Y_WEBGL',
    37441: 'UNPACK_PREMULTIPLY_ALPHA_WEBGL',
    37442: 'CONTEXT_LOST_WEBGL',
    37443: 'UNPACK_COLORSPACE_CONVERSION_WEBGL',
    37444: 'BROWSER_DEFAULT_WEBGL'
  }
  
  },{}],63:[function(require,module,exports){
  var gl10 = require('./1.0/numbers')
  
  module.exports = function lookupConstant (number) {
    return gl10[number]
  }
  
  },{"./1.0/numbers":62}],64:[function(require,module,exports){
  var raf = require('raf-component')
  
  module.exports = createContext
  
  function createContext(canvas, opts, render) {
    if (typeof opts === 'function') {
      render = opts
      opts = {}
    } else {
      opts = opts || {}
    }
  
    var gl = (
      canvas.getContext('webgl', opts) ||
      canvas.getContext('webgl-experimental', opts) ||
      canvas.getContext('experimental-webgl', opts)
    )
  
    if (!gl) {
      throw new Error('Unable to initialize WebGL')
    }
  
    if (render) raf(tick)
  
    return gl
  
    function tick() {
      render(gl)
      raf(tick)
    }
  }
  
  },{"raf-component":243}],65:[function(require,module,exports){
  
  var sprintf = require('sprintf-js').sprintf;
  var glConstants = require('gl-constants/lookup');
  var shaderName = require('glsl-shader-name');
  var addLineNumbers = require('add-line-numbers');
  
  module.exports = formatCompilerError;
  
  function formatCompilerError(errLog, src, type) {
      "use strict";
  
      var name = shaderName(src) || 'of unknown name (see npm glsl-shader-name)';
  
      var typeName = 'unknown type';
      if (type !== undefined) {
          typeName = type === glConstants.FRAGMENT_SHADER ? 'fragment' : 'vertex'
      }
  
      var longForm = sprintf('Error compiling %s shader %s:\n', typeName, name);
      var shortForm = sprintf("%s%s", longForm, errLog);
  
      var errorStrings = errLog.split('\n');
      var errors = {};
  
      for (var i = 0; i < errorStrings.length; i++) {
          var errorString = errorStrings[i];
          if (errorString === '') continue;
          var lineNo = parseInt(errorString.split(':')[2]);
          if (isNaN(lineNo)) {
              throw new Error(sprintf('Could not parse error: %s', errorString));
          }
          errors[lineNo] = errorString;
      }
  
      var lines = addLineNumbers(src).split('\n');
  
      for (var i = 0; i < lines.length; i++) {
          if (!errors[i+3] && !errors[i+2] && !errors[i+1]) continue;
          var line = lines[i];
          longForm += line + '\n';
          if (errors[i+1]) {
              var e = errors[i+1];
              e = e.substr(e.split(':', 3).join(':').length + 1).trim();
              longForm += sprintf('^^^ %s\n\n', e);
          }
      }
  
      return {
          long: longForm.trim(),
          short: shortForm.trim()
      };
  }
  
  
  },{"add-line-numbers":3,"gl-constants/lookup":63,"glsl-shader-name":186,"sprintf-js":257}],66:[function(require,module,exports){
  var normalize = require('./normalize')
  var glType = require('gl-to-dtype')
  var createVAO = require('gl-vao')
  var dtype = require('dtype')
  
  module.exports = GLGeometry
  
  function GLGeometry (gl) {
    if (!(this instanceof GLGeometry)) {
      return new GLGeometry(gl)
    }
  
    this._elementsType = 5123
    this._elementsBytes = 2
    this._attributes = []
    this._dirty = true
    this._attrLength = 0
    this._facesLength = 0
    this._index = null
    this._vao = null
    this._keys = []
    this.gl = gl
  }
  
  GLGeometry.prototype.dispose = function () {
    for (var i = 0; i < this._attributes.length; i++) {
      this._attributes[i].buffer.dispose()
    }
  
    this._attributes = []
    this._keys = []
    this._attrLength = 0 // Length of this attribute (the number of vertices it feeds)
    this._facesLength = 0 // Number of vertices needed to draw all faces
    this._dirty = true
  
    if (this._index) {
      this._index.dispose()
      this._index = null
    }
  
    if (this._vao) {
      this._vao.dispose()
      this._vao = null
    }
  }
  
  GLGeometry.prototype.faces = function faces (attr, opts) {
    var size = opts && opts.size || 3
    attr = attr.cells ? attr.cells : attr
  
    this._dirty = true
  
    if (this._index) {
      this._index.dispose()
    }
  
    this._index = normalize.create(this.gl
      , attr
      , size
      , this.gl.ELEMENT_ARRAY_BUFFER
      , 'uint16'
    )
  
    this._facesLength = this._index.length * size
    this._index = this._index.buffer
  
    return this
  }
  
  GLGeometry.prototype.attr = function attr (name, attr, opts) {
    // If we get a simplicial complex
    if (attr.cells && attr.positions) {
      return this.attr(name, attr.positions).faces(attr.cells, opts)
    }
  
    opts = opts || {}
    var size = opts.size || 3
  
    // Is this a known attribute (ie, an update)?
    var keyIndex = this._keys.indexOf(name)
    if (keyIndex > -1) {
      var toUpdate = this._attributes[keyIndex].buffer
      var offset = opts.offset || undefined
      normalize.update(toUpdate, attr, size, 'float32', offset)
      this._attrLength = toUpdate.length / size / 4
      return this
    }
  
    this._dirty = true
  
    var gl = this.gl
    var first = !this._attributes.length
  
    var attribute = normalize.create(gl, attr, size, gl.ARRAY_BUFFER, 'float32')
    if (!attribute) {
      throw new Error(
        'Unexpected attribute format: needs an ndarray, array, typed array, ' +
        'gl-buffer or simplicial complex'
      )
    }
  
    var buffer = attribute.buffer
    var length = attribute.length
  
    this._keys.push(name)
    this._attributes.push({
      size: size,
      buffer: buffer
    })
  
    if (first) {
      this._attrLength = length
    }
  
    return this
  }
  
  GLGeometry.prototype.bind = function bind (shader) {
    this.update()
    this._vao.bind()
  
    if (!this._keys) return
    if (!shader) return
  
    for (var i = 0; i < this._keys.length; i++) {
      var attr = shader.attributes[this._keys[i]]
      if (attr) attr.location = i
    }
  
    shader.bind()
  }
  
  GLGeometry.prototype.draw = function draw (mode, start, stop) {
    start = typeof start === 'undefined' ? 0 : start
    mode = typeof mode === 'undefined' ? this.gl.TRIANGLES : mode
  
    this.update()
  
    if (this._vao._useElements) {
      stop = typeof stop === 'undefined' ? this._facesLength : stop
      this.gl.drawElements(mode, stop - start, this._elementsType, start * this._elementsBytes)
    } else {
      stop = typeof stop === 'undefined' ? this._attrLength : stop
      this.gl.drawArrays(mode, start, stop - start)
    }
  }
  
  GLGeometry.prototype.unbind = function unbind () {
    this.update()
    this._vao.unbind()
  }
  
  GLGeometry.prototype.update = function update () {
    if (!this._dirty) return
    this._dirty = false
    if (this._vao) this._vao.dispose()
  
    this._vao = createVAO(this.gl, this._attributes, this._index)
    this._elementsType = this._vao._elementsType
    this._elementsBytes = dtype(
      glType(this._elementsType) || 'array'
    ).BYTES_PER_ELEMENT || 2
  }
  
  },{"./normalize":67,"dtype":53,"gl-to-dtype":136,"gl-vao":140}],67:[function(require,module,exports){
  var pack = require('array-pack-2d')
  var ista = require('is-typedarray')
  var createBuffer = require('gl-buffer')
  var isnd = require('isndarray')
  var dtype = require('dtype')
  
  module.exports.create = create
  module.exports.update = update
  
  function create (gl, attr, size, mode, type) {
    // if we get a gl-buffer
    if (attr.handle instanceof WebGLBuffer) {
      return {
        buffer: attr,
        length: attr.length / size / 4
      }
    }
  
    var arr = normalize(attr, size, type)
    return {
      buffer: createBuffer(gl, arr.data, mode),
      length: arr.length
    }
  }
  
  function update (buffer, attr, size, type, offset) {
    // if we get a gl-buffer
    if (attr.handle instanceof WebGLBuffer) {
      throw new Error('Unhandled update case: WebGLBuffer')
    }
  
    var arr = normalize(attr, size, type)
    buffer.update(arr.data, offset)
  }
  
  function normalize (attr, size, type) {
    // if we get a nested 2D array
    if (Array.isArray(attr) && Array.isArray(attr[0])) {
      return {
        data: pack(attr, type),
        length: attr.length
      }
    }
  
    // if we get a nested 2D array (with the second array being typed)
    if (Array.isArray(attr) && ista(attr[0])) {
      return {
        data: pack(attr, type),
        length: (attr.length * attr[0].length) / size
      }
    }
  
    // if we get a 1D array
    if (Array.isArray(attr)) {
      return {
        data: new (dtype(type))(attr),
        length: attr.length / size
      }
    }
  
    // if we get an ndarray
    if (isnd(attr)) {
      return {
        data: attr,
        length: ndlength(attr.shape) / size
      }
    }
  
    // if we get a typed array
    if (ista(attr)) {
      if (type && !(attr instanceof dtype(type))) {
        attr = convert(attr, dtype(type))
      }
  
      return {
        data: attr,
        length: attr.length / size
      }
    }
  }
  
  function ndlength (shape) {
    var length = 1
    for (var i = 0; i < shape.length; i++) length *= shape[i]
    return length
  }
  
  function convert (a, B) {
    var b = new B(a.length)
    for (var i = 0; i < a.length; i++) b[i] = a[i]
    return b
  }
  
  },{"array-pack-2d":4,"dtype":53,"gl-buffer":59,"is-typedarray":199,"isndarray":201}],68:[function(require,module,exports){
  module.exports = create
  
  /**
   * Creates a new identity mat3
   *
   * @alias mat3.create
   * @returns {mat3} a new 3x3 matrix
   */
  function create() {
    var out = new Float32Array(9)
    out[0] = 1
    out[1] = 0
    out[2] = 0
    out[3] = 0
    out[4] = 1
    out[5] = 0
    out[6] = 0
    out[7] = 0
    out[8] = 1
    return out
  }
  
  },{}],69:[function(require,module,exports){
  module.exports = adjoint;
  
  /**
   * Calculates the adjugate of a mat4
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the source matrix
   * @returns {mat4} out
   */
  function adjoint(out, a) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
  
      out[0]  =  (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
      out[1]  = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
      out[2]  =  (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
      out[3]  = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
      out[4]  = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
      out[5]  =  (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
      out[6]  = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
      out[7]  =  (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
      out[8]  =  (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
      out[9]  = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
      out[10] =  (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
      out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
      out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
      out[13] =  (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
      out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
      out[15] =  (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
      return out;
  };
  },{}],70:[function(require,module,exports){
  module.exports = clone;
  
  /**
   * Creates a new mat4 initialized with values from an existing matrix
   *
   * @param {mat4} a matrix to clone
   * @returns {mat4} a new 4x4 matrix
   */
  function clone(a) {
      var out = new Float32Array(16);
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      out[9] = a[9];
      out[10] = a[10];
      out[11] = a[11];
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
      return out;
  };
  },{}],71:[function(require,module,exports){
  module.exports = copy;
  
  /**
   * Copy the values from one mat4 to another
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the source matrix
   * @returns {mat4} out
   */
  function copy(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      out[9] = a[9];
      out[10] = a[10];
      out[11] = a[11];
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
      return out;
  };
  },{}],72:[function(require,module,exports){
  module.exports = create;
  
  /**
   * Creates a new identity mat4
   *
   * @returns {mat4} a new 4x4 matrix
   */
  function create() {
      var out = new Float32Array(16);
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 1;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  };
  },{}],73:[function(require,module,exports){
  module.exports = determinant;
  
  /**
   * Calculates the determinant of a mat4
   *
   * @param {mat4} a the source matrix
   * @returns {Number} determinant of a
   */
  function determinant(a) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
  
          b00 = a00 * a11 - a01 * a10,
          b01 = a00 * a12 - a02 * a10,
          b02 = a00 * a13 - a03 * a10,
          b03 = a01 * a12 - a02 * a11,
          b04 = a01 * a13 - a03 * a11,
          b05 = a02 * a13 - a03 * a12,
          b06 = a20 * a31 - a21 * a30,
          b07 = a20 * a32 - a22 * a30,
          b08 = a20 * a33 - a23 * a30,
          b09 = a21 * a32 - a22 * a31,
          b10 = a21 * a33 - a23 * a31,
          b11 = a22 * a33 - a23 * a32;
  
      // Calculate the determinant
      return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  };
  },{}],74:[function(require,module,exports){
  module.exports = fromQuat;
  
  /**
   * Creates a matrix from a quaternion rotation.
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {quat4} q Rotation quaternion
   * @returns {mat4} out
   */
  function fromQuat(out, q) {
      var x = q[0], y = q[1], z = q[2], w = q[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
  
          xx = x * x2,
          yx = y * x2,
          yy = y * y2,
          zx = z * x2,
          zy = z * y2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2;
  
      out[0] = 1 - yy - zz;
      out[1] = yx + wz;
      out[2] = zx - wy;
      out[3] = 0;
  
      out[4] = yx - wz;
      out[5] = 1 - xx - zz;
      out[6] = zy + wx;
      out[7] = 0;
  
      out[8] = zx + wy;
      out[9] = zy - wx;
      out[10] = 1 - xx - yy;
      out[11] = 0;
  
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
  
      return out;
  };
  },{}],75:[function(require,module,exports){
  module.exports = fromRotationTranslation;
  
  /**
   * Creates a matrix from a quaternion rotation and vector translation
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.translate(dest, vec);
   *     var quatMat = mat4.create();
   *     quat4.toMat4(quat, quatMat);
   *     mat4.multiply(dest, quatMat);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {quat4} q Rotation quaternion
   * @param {vec3} v Translation vector
   * @returns {mat4} out
   */
  function fromRotationTranslation(out, q, v) {
      // Quaternion math
      var x = q[0], y = q[1], z = q[2], w = q[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
  
          xx = x * x2,
          xy = x * y2,
          xz = x * z2,
          yy = y * y2,
          yz = y * z2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2;
  
      out[0] = 1 - (yy + zz);
      out[1] = xy + wz;
      out[2] = xz - wy;
      out[3] = 0;
      out[4] = xy - wz;
      out[5] = 1 - (xx + zz);
      out[6] = yz + wx;
      out[7] = 0;
      out[8] = xz + wy;
      out[9] = yz - wx;
      out[10] = 1 - (xx + yy);
      out[11] = 0;
      out[12] = v[0];
      out[13] = v[1];
      out[14] = v[2];
      out[15] = 1;
      
      return out;
  };
  },{}],76:[function(require,module,exports){
  module.exports = frustum;
  
  /**
   * Generates a frustum matrix with the given bounds
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {Number} left Left bound of the frustum
   * @param {Number} right Right bound of the frustum
   * @param {Number} bottom Bottom bound of the frustum
   * @param {Number} top Top bound of the frustum
   * @param {Number} near Near bound of the frustum
   * @param {Number} far Far bound of the frustum
   * @returns {mat4} out
   */
  function frustum(out, left, right, bottom, top, near, far) {
      var rl = 1 / (right - left),
          tb = 1 / (top - bottom),
          nf = 1 / (near - far);
      out[0] = (near * 2) * rl;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = (near * 2) * tb;
      out[6] = 0;
      out[7] = 0;
      out[8] = (right + left) * rl;
      out[9] = (top + bottom) * tb;
      out[10] = (far + near) * nf;
      out[11] = -1;
      out[12] = 0;
      out[13] = 0;
      out[14] = (far * near * 2) * nf;
      out[15] = 0;
      return out;
  };
  },{}],77:[function(require,module,exports){
  module.exports = identity;
  
  /**
   * Set a mat4 to the identity matrix
   *
   * @param {mat4} out the receiving matrix
   * @returns {mat4} out
   */
  function identity(out) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 1;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  };
  },{}],78:[function(require,module,exports){
  module.exports = {
    create: require('./create')
    , clone: require('./clone')
    , copy: require('./copy')
    , identity: require('./identity')
    , transpose: require('./transpose')
    , invert: require('./invert')
    , adjoint: require('./adjoint')
    , determinant: require('./determinant')
    , multiply: require('./multiply')
    , translate: require('./translate')
    , scale: require('./scale')
    , rotate: require('./rotate')
    , rotateX: require('./rotateX')
    , rotateY: require('./rotateY')
    , rotateZ: require('./rotateZ')
    , fromRotationTranslation: require('./fromRotationTranslation')
    , fromQuat: require('./fromQuat')
    , frustum: require('./frustum')
    , perspective: require('./perspective')
    , perspectiveFromFieldOfView: require('./perspectiveFromFieldOfView')
    , ortho: require('./ortho')
    , lookAt: require('./lookAt')
    , str: require('./str')
  }
  },{"./adjoint":69,"./clone":70,"./copy":71,"./create":72,"./determinant":73,"./fromQuat":74,"./fromRotationTranslation":75,"./frustum":76,"./identity":77,"./invert":79,"./lookAt":80,"./multiply":81,"./ortho":82,"./perspective":83,"./perspectiveFromFieldOfView":84,"./rotate":85,"./rotateX":86,"./rotateY":87,"./rotateZ":88,"./scale":89,"./str":90,"./translate":91,"./transpose":92}],79:[function(require,module,exports){
  module.exports = invert;
  
  /**
   * Inverts a mat4
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the source matrix
   * @returns {mat4} out
   */
  function invert(out, a) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
  
          b00 = a00 * a11 - a01 * a10,
          b01 = a00 * a12 - a02 * a10,
          b02 = a00 * a13 - a03 * a10,
          b03 = a01 * a12 - a02 * a11,
          b04 = a01 * a13 - a03 * a11,
          b05 = a02 * a13 - a03 * a12,
          b06 = a20 * a31 - a21 * a30,
          b07 = a20 * a32 - a22 * a30,
          b08 = a20 * a33 - a23 * a30,
          b09 = a21 * a32 - a22 * a31,
          b10 = a21 * a33 - a23 * a31,
          b11 = a22 * a33 - a23 * a32,
  
          // Calculate the determinant
          det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  
      if (!det) { 
          return null; 
      }
      det = 1.0 / det;
  
      out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
      out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
      out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
      out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
      out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
      out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
      out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
      out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
      out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
      out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
      out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
      out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
      out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
      out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
      out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
      out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  
      return out;
  };
  },{}],80:[function(require,module,exports){
  var identity = require('./identity');
  
  module.exports = lookAt;
  
  /**
   * Generates a look-at matrix with the given eye position, focal point, and up axis
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {vec3} eye Position of the viewer
   * @param {vec3} center Point the viewer is looking at
   * @param {vec3} up vec3 pointing up
   * @returns {mat4} out
   */
  function lookAt(out, eye, center, up) {
      var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
          eyex = eye[0],
          eyey = eye[1],
          eyez = eye[2],
          upx = up[0],
          upy = up[1],
          upz = up[2],
          centerx = center[0],
          centery = center[1],
          centerz = center[2];
  
      if (Math.abs(eyex - centerx) < 0.000001 &&
          Math.abs(eyey - centery) < 0.000001 &&
          Math.abs(eyez - centerz) < 0.000001) {
          return identity(out);
      }
  
      z0 = eyex - centerx;
      z1 = eyey - centery;
      z2 = eyez - centerz;
  
      len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
      z0 *= len;
      z1 *= len;
      z2 *= len;
  
      x0 = upy * z2 - upz * z1;
      x1 = upz * z0 - upx * z2;
      x2 = upx * z1 - upy * z0;
      len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
      if (!len) {
          x0 = 0;
          x1 = 0;
          x2 = 0;
      } else {
          len = 1 / len;
          x0 *= len;
          x1 *= len;
          x2 *= len;
      }
  
      y0 = z1 * x2 - z2 * x1;
      y1 = z2 * x0 - z0 * x2;
      y2 = z0 * x1 - z1 * x0;
  
      len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
      if (!len) {
          y0 = 0;
          y1 = 0;
          y2 = 0;
      } else {
          len = 1 / len;
          y0 *= len;
          y1 *= len;
          y2 *= len;
      }
  
      out[0] = x0;
      out[1] = y0;
      out[2] = z0;
      out[3] = 0;
      out[4] = x1;
      out[5] = y1;
      out[6] = z1;
      out[7] = 0;
      out[8] = x2;
      out[9] = y2;
      out[10] = z2;
      out[11] = 0;
      out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
      out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
      out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
      out[15] = 1;
  
      return out;
  };
  },{"./identity":77}],81:[function(require,module,exports){
  module.exports = multiply;
  
  /**
   * Multiplies two mat4's
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the first operand
   * @param {mat4} b the second operand
   * @returns {mat4} out
   */
  function multiply(out, a, b) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
  
      // Cache only the current line of the second matrix
      var b0  = b[0], b1 = b[1], b2 = b[2], b3 = b[3];  
      out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
      out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
      out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
      out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  
      b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
      out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
      out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
      out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
      out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  
      b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
      out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
      out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
      out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
      out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  
      b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
      out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
      out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
      out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
      out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
      return out;
  };
  },{}],82:[function(require,module,exports){
  module.exports = ortho;
  
  /**
   * Generates a orthogonal projection matrix with the given bounds
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {number} left Left bound of the frustum
   * @param {number} right Right bound of the frustum
   * @param {number} bottom Bottom bound of the frustum
   * @param {number} top Top bound of the frustum
   * @param {number} near Near bound of the frustum
   * @param {number} far Far bound of the frustum
   * @returns {mat4} out
   */
  function ortho(out, left, right, bottom, top, near, far) {
      var lr = 1 / (left - right),
          bt = 1 / (bottom - top),
          nf = 1 / (near - far);
      out[0] = -2 * lr;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = -2 * bt;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 2 * nf;
      out[11] = 0;
      out[12] = (left + right) * lr;
      out[13] = (top + bottom) * bt;
      out[14] = (far + near) * nf;
      out[15] = 1;
      return out;
  };
  },{}],83:[function(require,module,exports){
  module.exports = perspective;
  
  /**
   * Generates a perspective projection matrix with the given bounds
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {number} fovy Vertical field of view in radians
   * @param {number} aspect Aspect ratio. typically viewport width/height
   * @param {number} near Near bound of the frustum
   * @param {number} far Far bound of the frustum
   * @returns {mat4} out
   */
  function perspective(out, fovy, aspect, near, far) {
      var f = 1.0 / Math.tan(fovy / 2),
          nf = 1 / (near - far);
      out[0] = f / aspect;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = f;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = (far + near) * nf;
      out[11] = -1;
      out[12] = 0;
      out[13] = 0;
      out[14] = (2 * far * near) * nf;
      out[15] = 0;
      return out;
  };
  },{}],84:[function(require,module,exports){
  module.exports = perspectiveFromFieldOfView;
  
  /**
   * Generates a perspective projection matrix with the given field of view.
   * This is primarily useful for generating projection matrices to be used
   * with the still experiemental WebVR API.
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {number} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
   * @param {number} near Near bound of the frustum
   * @param {number} far Far bound of the frustum
   * @returns {mat4} out
   */
  function perspectiveFromFieldOfView(out, fov, near, far) {
      var upTan = Math.tan(fov.upDegrees * Math.PI/180.0),
          downTan = Math.tan(fov.downDegrees * Math.PI/180.0),
          leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0),
          rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0),
          xScale = 2.0 / (leftTan + rightTan),
          yScale = 2.0 / (upTan + downTan);
  
      out[0] = xScale;
      out[1] = 0.0;
      out[2] = 0.0;
      out[3] = 0.0;
      out[4] = 0.0;
      out[5] = yScale;
      out[6] = 0.0;
      out[7] = 0.0;
      out[8] = -((leftTan - rightTan) * xScale * 0.5);
      out[9] = ((upTan - downTan) * yScale * 0.5);
      out[10] = far / (near - far);
      out[11] = -1.0;
      out[12] = 0.0;
      out[13] = 0.0;
      out[14] = (far * near) / (near - far);
      out[15] = 0.0;
      return out;
  }
  
  
  },{}],85:[function(require,module,exports){
  module.exports = rotate;
  
  /**
   * Rotates a mat4 by the given angle
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @param {vec3} axis the axis to rotate around
   * @returns {mat4} out
   */
  function rotate(out, a, rad, axis) {
      var x = axis[0], y = axis[1], z = axis[2],
          len = Math.sqrt(x * x + y * y + z * z),
          s, c, t,
          a00, a01, a02, a03,
          a10, a11, a12, a13,
          a20, a21, a22, a23,
          b00, b01, b02,
          b10, b11, b12,
          b20, b21, b22;
  
      if (Math.abs(len) < 0.000001) { return null; }
      
      len = 1 / len;
      x *= len;
      y *= len;
      z *= len;
  
      s = Math.sin(rad);
      c = Math.cos(rad);
      t = 1 - c;
  
      a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
      a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
      a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
  
      // Construct the elements of the rotation matrix
      b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
      b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
      b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
  
      // Perform rotation-specific matrix multiplication
      out[0] = a00 * b00 + a10 * b01 + a20 * b02;
      out[1] = a01 * b00 + a11 * b01 + a21 * b02;
      out[2] = a02 * b00 + a12 * b01 + a22 * b02;
      out[3] = a03 * b00 + a13 * b01 + a23 * b02;
      out[4] = a00 * b10 + a10 * b11 + a20 * b12;
      out[5] = a01 * b10 + a11 * b11 + a21 * b12;
      out[6] = a02 * b10 + a12 * b11 + a22 * b12;
      out[7] = a03 * b10 + a13 * b11 + a23 * b12;
      out[8] = a00 * b20 + a10 * b21 + a20 * b22;
      out[9] = a01 * b20 + a11 * b21 + a21 * b22;
      out[10] = a02 * b20 + a12 * b21 + a22 * b22;
      out[11] = a03 * b20 + a13 * b21 + a23 * b22;
  
      if (a !== out) { // If the source and destination differ, copy the unchanged last row
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
      return out;
  };
  },{}],86:[function(require,module,exports){
  module.exports = rotateX;
  
  /**
   * Rotates a matrix by the given angle around the X axis
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  function rotateX(out, a, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad),
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11];
  
      if (a !== out) { // If the source and destination differ, copy the unchanged rows
          out[0]  = a[0];
          out[1]  = a[1];
          out[2]  = a[2];
          out[3]  = a[3];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      // Perform axis-specific matrix multiplication
      out[4] = a10 * c + a20 * s;
      out[5] = a11 * c + a21 * s;
      out[6] = a12 * c + a22 * s;
      out[7] = a13 * c + a23 * s;
      out[8] = a20 * c - a10 * s;
      out[9] = a21 * c - a11 * s;
      out[10] = a22 * c - a12 * s;
      out[11] = a23 * c - a13 * s;
      return out;
  };
  },{}],87:[function(require,module,exports){
  module.exports = rotateY;
  
  /**
   * Rotates a matrix by the given angle around the Y axis
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  function rotateY(out, a, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad),
          a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11];
  
      if (a !== out) { // If the source and destination differ, copy the unchanged rows
          out[4]  = a[4];
          out[5]  = a[5];
          out[6]  = a[6];
          out[7]  = a[7];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      // Perform axis-specific matrix multiplication
      out[0] = a00 * c - a20 * s;
      out[1] = a01 * c - a21 * s;
      out[2] = a02 * c - a22 * s;
      out[3] = a03 * c - a23 * s;
      out[8] = a00 * s + a20 * c;
      out[9] = a01 * s + a21 * c;
      out[10] = a02 * s + a22 * c;
      out[11] = a03 * s + a23 * c;
      return out;
  };
  },{}],88:[function(require,module,exports){
  module.exports = rotateZ;
  
  /**
   * Rotates a matrix by the given angle around the Z axis
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  function rotateZ(out, a, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad),
          a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7];
  
      if (a !== out) { // If the source and destination differ, copy the unchanged last row
          out[8]  = a[8];
          out[9]  = a[9];
          out[10] = a[10];
          out[11] = a[11];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      // Perform axis-specific matrix multiplication
      out[0] = a00 * c + a10 * s;
      out[1] = a01 * c + a11 * s;
      out[2] = a02 * c + a12 * s;
      out[3] = a03 * c + a13 * s;
      out[4] = a10 * c - a00 * s;
      out[5] = a11 * c - a01 * s;
      out[6] = a12 * c - a02 * s;
      out[7] = a13 * c - a03 * s;
      return out;
  };
  },{}],89:[function(require,module,exports){
  module.exports = scale;
  
  /**
   * Scales the mat4 by the dimensions in the given vec3
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to scale
   * @param {vec3} v the vec3 to scale the matrix by
   * @returns {mat4} out
   **/
  function scale(out, a, v) {
      var x = v[0], y = v[1], z = v[2];
  
      out[0] = a[0] * x;
      out[1] = a[1] * x;
      out[2] = a[2] * x;
      out[3] = a[3] * x;
      out[4] = a[4] * y;
      out[5] = a[5] * y;
      out[6] = a[6] * y;
      out[7] = a[7] * y;
      out[8] = a[8] * z;
      out[9] = a[9] * z;
      out[10] = a[10] * z;
      out[11] = a[11] * z;
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
      return out;
  };
  },{}],90:[function(require,module,exports){
  module.exports = str;
  
  /**
   * Returns a string representation of a mat4
   *
   * @param {mat4} mat matrix to represent as a string
   * @returns {String} string representation of the matrix
   */
  function str(a) {
      return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
                      a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
                      a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + 
                      a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
  };
  },{}],91:[function(require,module,exports){
  module.exports = translate;
  
  /**
   * Translate a mat4 by the given vector
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to translate
   * @param {vec3} v vector to translate by
   * @returns {mat4} out
   */
  function translate(out, a, v) {
      var x = v[0], y = v[1], z = v[2],
          a00, a01, a02, a03,
          a10, a11, a12, a13,
          a20, a21, a22, a23;
  
      if (a === out) {
          out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
          out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
          out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
          out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
      } else {
          a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
          a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
          a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
  
          out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
          out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
          out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
  
          out[12] = a00 * x + a10 * y + a20 * z + a[12];
          out[13] = a01 * x + a11 * y + a21 * z + a[13];
          out[14] = a02 * x + a12 * y + a22 * z + a[14];
          out[15] = a03 * x + a13 * y + a23 * z + a[15];
      }
  
      return out;
  };
  },{}],92:[function(require,module,exports){
  module.exports = transpose;
  
  /**
   * Transpose the values of a mat4
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the source matrix
   * @returns {mat4} out
   */
  function transpose(out, a) {
      // If we are transposing ourselves we can skip a few steps but have to cache some values
      if (out === a) {
          var a01 = a[1], a02 = a[2], a03 = a[3],
              a12 = a[6], a13 = a[7],
              a23 = a[11];
  
          out[1] = a[4];
          out[2] = a[8];
          out[3] = a[12];
          out[4] = a01;
          out[6] = a[9];
          out[7] = a[13];
          out[8] = a02;
          out[9] = a12;
          out[11] = a[14];
          out[12] = a03;
          out[13] = a13;
          out[14] = a23;
      } else {
          out[0] = a[0];
          out[1] = a[4];
          out[2] = a[8];
          out[3] = a[12];
          out[4] = a[1];
          out[5] = a[5];
          out[6] = a[9];
          out[7] = a[13];
          out[8] = a[2];
          out[9] = a[6];
          out[10] = a[10];
          out[11] = a[14];
          out[12] = a[3];
          out[13] = a[7];
          out[14] = a[11];
          out[15] = a[15];
      }
      
      return out;
  };
  },{}],93:[function(require,module,exports){
  /**
   * @fileoverview gl-matrix - High performance matrix and vector operations
   * @author Brandon Jones
   * @author Colin MacKenzie IV
   * @version 2.3.0
   */
  
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  // END HEADER
  
  exports.glMatrix = require("./gl-matrix/common.js");
  exports.mat2 = require("./gl-matrix/mat2.js");
  exports.mat2d = require("./gl-matrix/mat2d.js");
  exports.mat3 = require("./gl-matrix/mat3.js");
  exports.mat4 = require("./gl-matrix/mat4.js");
  exports.quat = require("./gl-matrix/quat.js");
  exports.vec2 = require("./gl-matrix/vec2.js");
  exports.vec3 = require("./gl-matrix/vec3.js");
  exports.vec4 = require("./gl-matrix/vec4.js");
  },{"./gl-matrix/common.js":94,"./gl-matrix/mat2.js":95,"./gl-matrix/mat2d.js":96,"./gl-matrix/mat3.js":97,"./gl-matrix/mat4.js":98,"./gl-matrix/quat.js":99,"./gl-matrix/vec2.js":100,"./gl-matrix/vec3.js":101,"./gl-matrix/vec4.js":102}],94:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  /**
   * @class Common utilities
   * @name glMatrix
   */
  var glMatrix = {};
  
  // Constants
  glMatrix.EPSILON = 0.000001;
  glMatrix.ARRAY_TYPE = (typeof Float32Array !== 'undefined') ? Float32Array : Array;
  glMatrix.RANDOM = Math.random;
  
  /**
   * Sets the type of array used when creating new vectors and matrices
   *
   * @param {Type} type Array type, such as Float32Array or Array
   */
  glMatrix.setMatrixArrayType = function(type) {
      GLMAT_ARRAY_TYPE = type;
  }
  
  var degree = Math.PI / 180;
  
  /**
  * Convert Degree To Radian
  *
  * @param {Number} Angle in Degrees
  */
  glMatrix.toRadian = function(a){
       return a * degree;
  }
  
  module.exports = glMatrix;
  
  },{}],95:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  var glMatrix = require("./common.js");
  
  /**
   * @class 2x2 Matrix
   * @name mat2
   */
  var mat2 = {};
  
  /**
   * Creates a new identity mat2
   *
   * @returns {mat2} a new 2x2 matrix
   */
  mat2.create = function() {
      var out = new glMatrix.ARRAY_TYPE(4);
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      return out;
  };
  
  /**
   * Creates a new mat2 initialized with values from an existing matrix
   *
   * @param {mat2} a matrix to clone
   * @returns {mat2} a new 2x2 matrix
   */
  mat2.clone = function(a) {
      var out = new glMatrix.ARRAY_TYPE(4);
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      return out;
  };
  
  /**
   * Copy the values from one mat2 to another
   *
   * @param {mat2} out the receiving matrix
   * @param {mat2} a the source matrix
   * @returns {mat2} out
   */
  mat2.copy = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      return out;
  };
  
  /**
   * Set a mat2 to the identity matrix
   *
   * @param {mat2} out the receiving matrix
   * @returns {mat2} out
   */
  mat2.identity = function(out) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      return out;
  };
  
  /**
   * Transpose the values of a mat2
   *
   * @param {mat2} out the receiving matrix
   * @param {mat2} a the source matrix
   * @returns {mat2} out
   */
  mat2.transpose = function(out, a) {
      // If we are transposing ourselves we can skip a few steps but have to cache some values
      if (out === a) {
          var a1 = a[1];
          out[1] = a[2];
          out[2] = a1;
      } else {
          out[0] = a[0];
          out[1] = a[2];
          out[2] = a[1];
          out[3] = a[3];
      }
      
      return out;
  };
  
  /**
   * Inverts a mat2
   *
   * @param {mat2} out the receiving matrix
   * @param {mat2} a the source matrix
   * @returns {mat2} out
   */
  mat2.invert = function(out, a) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
  
          // Calculate the determinant
          det = a0 * a3 - a2 * a1;
  
      if (!det) {
          return null;
      }
      det = 1.0 / det;
      
      out[0] =  a3 * det;
      out[1] = -a1 * det;
      out[2] = -a2 * det;
      out[3] =  a0 * det;
  
      return out;
  };
  
  /**
   * Calculates the adjugate of a mat2
   *
   * @param {mat2} out the receiving matrix
   * @param {mat2} a the source matrix
   * @returns {mat2} out
   */
  mat2.adjoint = function(out, a) {
      // Caching this value is nessecary if out == a
      var a0 = a[0];
      out[0] =  a[3];
      out[1] = -a[1];
      out[2] = -a[2];
      out[3] =  a0;
  
      return out;
  };
  
  /**
   * Calculates the determinant of a mat2
   *
   * @param {mat2} a the source matrix
   * @returns {Number} determinant of a
   */
  mat2.determinant = function (a) {
      return a[0] * a[3] - a[2] * a[1];
  };
  
  /**
   * Multiplies two mat2's
   *
   * @param {mat2} out the receiving matrix
   * @param {mat2} a the first operand
   * @param {mat2} b the second operand
   * @returns {mat2} out
   */
  mat2.multiply = function (out, a, b) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
      var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
      out[0] = a0 * b0 + a2 * b1;
      out[1] = a1 * b0 + a3 * b1;
      out[2] = a0 * b2 + a2 * b3;
      out[3] = a1 * b2 + a3 * b3;
      return out;
  };
  
  /**
   * Alias for {@link mat2.multiply}
   * @function
   */
  mat2.mul = mat2.multiply;
  
  /**
   * Rotates a mat2 by the given angle
   *
   * @param {mat2} out the receiving matrix
   * @param {mat2} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat2} out
   */
  mat2.rotate = function (out, a, rad) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
          s = Math.sin(rad),
          c = Math.cos(rad);
      out[0] = a0 *  c + a2 * s;
      out[1] = a1 *  c + a3 * s;
      out[2] = a0 * -s + a2 * c;
      out[3] = a1 * -s + a3 * c;
      return out;
  };
  
  /**
   * Scales the mat2 by the dimensions in the given vec2
   *
   * @param {mat2} out the receiving matrix
   * @param {mat2} a the matrix to rotate
   * @param {vec2} v the vec2 to scale the matrix by
   * @returns {mat2} out
   **/
  mat2.scale = function(out, a, v) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
          v0 = v[0], v1 = v[1];
      out[0] = a0 * v0;
      out[1] = a1 * v0;
      out[2] = a2 * v1;
      out[3] = a3 * v1;
      return out;
  };
  
  /**
   * Creates a matrix from a given angle
   * This is equivalent to (but much faster than):
   *
   *     mat2.identity(dest);
   *     mat2.rotate(dest, dest, rad);
   *
   * @param {mat2} out mat2 receiving operation result
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat2} out
   */
  mat2.fromRotation = function(out, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad);
      out[0] = c;
      out[1] = s;
      out[2] = -s;
      out[3] = c;
      return out;
  }
  
  /**
   * Creates a matrix from a vector scaling
   * This is equivalent to (but much faster than):
   *
   *     mat2.identity(dest);
   *     mat2.scale(dest, dest, vec);
   *
   * @param {mat2} out mat2 receiving operation result
   * @param {vec2} v Scaling vector
   * @returns {mat2} out
   */
  mat2.fromScaling = function(out, v) {
      out[0] = v[0];
      out[1] = 0;
      out[2] = 0;
      out[3] = v[1];
      return out;
  }
  
  /**
   * Returns a string representation of a mat2
   *
   * @param {mat2} mat matrix to represent as a string
   * @returns {String} string representation of the matrix
   */
  mat2.str = function (a) {
      return 'mat2(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
  };
  
  /**
   * Returns Frobenius norm of a mat2
   *
   * @param {mat2} a the matrix to calculate Frobenius norm of
   * @returns {Number} Frobenius norm
   */
  mat2.frob = function (a) {
      return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2)))
  };
  
  /**
   * Returns L, D and U matrices (Lower triangular, Diagonal and Upper triangular) by factorizing the input matrix
   * @param {mat2} L the lower triangular matrix 
   * @param {mat2} D the diagonal matrix 
   * @param {mat2} U the upper triangular matrix 
   * @param {mat2} a the input matrix to factorize
   */
  
  mat2.LDU = function (L, D, U, a) { 
      L[2] = a[2]/a[0]; 
      U[0] = a[0]; 
      U[1] = a[1]; 
      U[3] = a[3] - L[2] * U[1]; 
      return [L, D, U];       
  }; 
  
  
  module.exports = mat2;
  
  },{"./common.js":94}],96:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  var glMatrix = require("./common.js");
  
  /**
   * @class 2x3 Matrix
   * @name mat2d
   * 
   * @description 
   * A mat2d contains six elements defined as:
   * <pre>
   * [a, c, tx,
   *  b, d, ty]
   * </pre>
   * This is a short form for the 3x3 matrix:
   * <pre>
   * [a, c, tx,
   *  b, d, ty,
   *  0, 0, 1]
   * </pre>
   * The last row is ignored so the array is shorter and operations are faster.
   */
  var mat2d = {};
  
  /**
   * Creates a new identity mat2d
   *
   * @returns {mat2d} a new 2x3 matrix
   */
  mat2d.create = function() {
      var out = new glMatrix.ARRAY_TYPE(6);
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      out[4] = 0;
      out[5] = 0;
      return out;
  };
  
  /**
   * Creates a new mat2d initialized with values from an existing matrix
   *
   * @param {mat2d} a matrix to clone
   * @returns {mat2d} a new 2x3 matrix
   */
  mat2d.clone = function(a) {
      var out = new glMatrix.ARRAY_TYPE(6);
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      return out;
  };
  
  /**
   * Copy the values from one mat2d to another
   *
   * @param {mat2d} out the receiving matrix
   * @param {mat2d} a the source matrix
   * @returns {mat2d} out
   */
  mat2d.copy = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      return out;
  };
  
  /**
   * Set a mat2d to the identity matrix
   *
   * @param {mat2d} out the receiving matrix
   * @returns {mat2d} out
   */
  mat2d.identity = function(out) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      out[4] = 0;
      out[5] = 0;
      return out;
  };
  
  /**
   * Inverts a mat2d
   *
   * @param {mat2d} out the receiving matrix
   * @param {mat2d} a the source matrix
   * @returns {mat2d} out
   */
  mat2d.invert = function(out, a) {
      var aa = a[0], ab = a[1], ac = a[2], ad = a[3],
          atx = a[4], aty = a[5];
  
      var det = aa * ad - ab * ac;
      if(!det){
          return null;
      }
      det = 1.0 / det;
  
      out[0] = ad * det;
      out[1] = -ab * det;
      out[2] = -ac * det;
      out[3] = aa * det;
      out[4] = (ac * aty - ad * atx) * det;
      out[5] = (ab * atx - aa * aty) * det;
      return out;
  };
  
  /**
   * Calculates the determinant of a mat2d
   *
   * @param {mat2d} a the source matrix
   * @returns {Number} determinant of a
   */
  mat2d.determinant = function (a) {
      return a[0] * a[3] - a[1] * a[2];
  };
  
  /**
   * Multiplies two mat2d's
   *
   * @param {mat2d} out the receiving matrix
   * @param {mat2d} a the first operand
   * @param {mat2d} b the second operand
   * @returns {mat2d} out
   */
  mat2d.multiply = function (out, a, b) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
          b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
      out[0] = a0 * b0 + a2 * b1;
      out[1] = a1 * b0 + a3 * b1;
      out[2] = a0 * b2 + a2 * b3;
      out[3] = a1 * b2 + a3 * b3;
      out[4] = a0 * b4 + a2 * b5 + a4;
      out[5] = a1 * b4 + a3 * b5 + a5;
      return out;
  };
  
  /**
   * Alias for {@link mat2d.multiply}
   * @function
   */
  mat2d.mul = mat2d.multiply;
  
  /**
   * Rotates a mat2d by the given angle
   *
   * @param {mat2d} out the receiving matrix
   * @param {mat2d} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat2d} out
   */
  mat2d.rotate = function (out, a, rad) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
          s = Math.sin(rad),
          c = Math.cos(rad);
      out[0] = a0 *  c + a2 * s;
      out[1] = a1 *  c + a3 * s;
      out[2] = a0 * -s + a2 * c;
      out[3] = a1 * -s + a3 * c;
      out[4] = a4;
      out[5] = a5;
      return out;
  };
  
  /**
   * Scales the mat2d by the dimensions in the given vec2
   *
   * @param {mat2d} out the receiving matrix
   * @param {mat2d} a the matrix to translate
   * @param {vec2} v the vec2 to scale the matrix by
   * @returns {mat2d} out
   **/
  mat2d.scale = function(out, a, v) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
          v0 = v[0], v1 = v[1];
      out[0] = a0 * v0;
      out[1] = a1 * v0;
      out[2] = a2 * v1;
      out[3] = a3 * v1;
      out[4] = a4;
      out[5] = a5;
      return out;
  };
  
  /**
   * Translates the mat2d by the dimensions in the given vec2
   *
   * @param {mat2d} out the receiving matrix
   * @param {mat2d} a the matrix to translate
   * @param {vec2} v the vec2 to translate the matrix by
   * @returns {mat2d} out
   **/
  mat2d.translate = function(out, a, v) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
          v0 = v[0], v1 = v[1];
      out[0] = a0;
      out[1] = a1;
      out[2] = a2;
      out[3] = a3;
      out[4] = a0 * v0 + a2 * v1 + a4;
      out[5] = a1 * v0 + a3 * v1 + a5;
      return out;
  };
  
  /**
   * Creates a matrix from a given angle
   * This is equivalent to (but much faster than):
   *
   *     mat2d.identity(dest);
   *     mat2d.rotate(dest, dest, rad);
   *
   * @param {mat2d} out mat2d receiving operation result
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat2d} out
   */
  mat2d.fromRotation = function(out, rad) {
      var s = Math.sin(rad), c = Math.cos(rad);
      out[0] = c;
      out[1] = s;
      out[2] = -s;
      out[3] = c;
      out[4] = 0;
      out[5] = 0;
      return out;
  }
  
  /**
   * Creates a matrix from a vector scaling
   * This is equivalent to (but much faster than):
   *
   *     mat2d.identity(dest);
   *     mat2d.scale(dest, dest, vec);
   *
   * @param {mat2d} out mat2d receiving operation result
   * @param {vec2} v Scaling vector
   * @returns {mat2d} out
   */
  mat2d.fromScaling = function(out, v) {
      out[0] = v[0];
      out[1] = 0;
      out[2] = 0;
      out[3] = v[1];
      out[4] = 0;
      out[5] = 0;
      return out;
  }
  
  /**
   * Creates a matrix from a vector translation
   * This is equivalent to (but much faster than):
   *
   *     mat2d.identity(dest);
   *     mat2d.translate(dest, dest, vec);
   *
   * @param {mat2d} out mat2d receiving operation result
   * @param {vec2} v Translation vector
   * @returns {mat2d} out
   */
  mat2d.fromTranslation = function(out, v) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      out[4] = v[0];
      out[5] = v[1];
      return out;
  }
  
  /**
   * Returns a string representation of a mat2d
   *
   * @param {mat2d} a matrix to represent as a string
   * @returns {String} string representation of the matrix
   */
  mat2d.str = function (a) {
      return 'mat2d(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + 
                      a[3] + ', ' + a[4] + ', ' + a[5] + ')';
  };
  
  /**
   * Returns Frobenius norm of a mat2d
   *
   * @param {mat2d} a the matrix to calculate Frobenius norm of
   * @returns {Number} Frobenius norm
   */
  mat2d.frob = function (a) { 
      return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + 1))
  }; 
  
  module.exports = mat2d;
  
  },{"./common.js":94}],97:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  var glMatrix = require("./common.js");
  
  /**
   * @class 3x3 Matrix
   * @name mat3
   */
  var mat3 = {};
  
  /**
   * Creates a new identity mat3
   *
   * @returns {mat3} a new 3x3 matrix
   */
  mat3.create = function() {
      var out = new glMatrix.ARRAY_TYPE(9);
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 1;
      out[5] = 0;
      out[6] = 0;
      out[7] = 0;
      out[8] = 1;
      return out;
  };
  
  /**
   * Copies the upper-left 3x3 values into the given mat3.
   *
   * @param {mat3} out the receiving 3x3 matrix
   * @param {mat4} a   the source 4x4 matrix
   * @returns {mat3} out
   */
  mat3.fromMat4 = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[4];
      out[4] = a[5];
      out[5] = a[6];
      out[6] = a[8];
      out[7] = a[9];
      out[8] = a[10];
      return out;
  };
  
  /**
   * Creates a new mat3 initialized with values from an existing matrix
   *
   * @param {mat3} a matrix to clone
   * @returns {mat3} a new 3x3 matrix
   */
  mat3.clone = function(a) {
      var out = new glMatrix.ARRAY_TYPE(9);
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      return out;
  };
  
  /**
   * Copy the values from one mat3 to another
   *
   * @param {mat3} out the receiving matrix
   * @param {mat3} a the source matrix
   * @returns {mat3} out
   */
  mat3.copy = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      return out;
  };
  
  /**
   * Set a mat3 to the identity matrix
   *
   * @param {mat3} out the receiving matrix
   * @returns {mat3} out
   */
  mat3.identity = function(out) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 1;
      out[5] = 0;
      out[6] = 0;
      out[7] = 0;
      out[8] = 1;
      return out;
  };
  
  /**
   * Transpose the values of a mat3
   *
   * @param {mat3} out the receiving matrix
   * @param {mat3} a the source matrix
   * @returns {mat3} out
   */
  mat3.transpose = function(out, a) {
      // If we are transposing ourselves we can skip a few steps but have to cache some values
      if (out === a) {
          var a01 = a[1], a02 = a[2], a12 = a[5];
          out[1] = a[3];
          out[2] = a[6];
          out[3] = a01;
          out[5] = a[7];
          out[6] = a02;
          out[7] = a12;
      } else {
          out[0] = a[0];
          out[1] = a[3];
          out[2] = a[6];
          out[3] = a[1];
          out[4] = a[4];
          out[5] = a[7];
          out[6] = a[2];
          out[7] = a[5];
          out[8] = a[8];
      }
      
      return out;
  };
  
  /**
   * Inverts a mat3
   *
   * @param {mat3} out the receiving matrix
   * @param {mat3} a the source matrix
   * @returns {mat3} out
   */
  mat3.invert = function(out, a) {
      var a00 = a[0], a01 = a[1], a02 = a[2],
          a10 = a[3], a11 = a[4], a12 = a[5],
          a20 = a[6], a21 = a[7], a22 = a[8],
  
          b01 = a22 * a11 - a12 * a21,
          b11 = -a22 * a10 + a12 * a20,
          b21 = a21 * a10 - a11 * a20,
  
          // Calculate the determinant
          det = a00 * b01 + a01 * b11 + a02 * b21;
  
      if (!det) { 
          return null; 
      }
      det = 1.0 / det;
  
      out[0] = b01 * det;
      out[1] = (-a22 * a01 + a02 * a21) * det;
      out[2] = (a12 * a01 - a02 * a11) * det;
      out[3] = b11 * det;
      out[4] = (a22 * a00 - a02 * a20) * det;
      out[5] = (-a12 * a00 + a02 * a10) * det;
      out[6] = b21 * det;
      out[7] = (-a21 * a00 + a01 * a20) * det;
      out[8] = (a11 * a00 - a01 * a10) * det;
      return out;
  };
  
  /**
   * Calculates the adjugate of a mat3
   *
   * @param {mat3} out the receiving matrix
   * @param {mat3} a the source matrix
   * @returns {mat3} out
   */
  mat3.adjoint = function(out, a) {
      var a00 = a[0], a01 = a[1], a02 = a[2],
          a10 = a[3], a11 = a[4], a12 = a[5],
          a20 = a[6], a21 = a[7], a22 = a[8];
  
      out[0] = (a11 * a22 - a12 * a21);
      out[1] = (a02 * a21 - a01 * a22);
      out[2] = (a01 * a12 - a02 * a11);
      out[3] = (a12 * a20 - a10 * a22);
      out[4] = (a00 * a22 - a02 * a20);
      out[5] = (a02 * a10 - a00 * a12);
      out[6] = (a10 * a21 - a11 * a20);
      out[7] = (a01 * a20 - a00 * a21);
      out[8] = (a00 * a11 - a01 * a10);
      return out;
  };
  
  /**
   * Calculates the determinant of a mat3
   *
   * @param {mat3} a the source matrix
   * @returns {Number} determinant of a
   */
  mat3.determinant = function (a) {
      var a00 = a[0], a01 = a[1], a02 = a[2],
          a10 = a[3], a11 = a[4], a12 = a[5],
          a20 = a[6], a21 = a[7], a22 = a[8];
  
      return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
  };
  
  /**
   * Multiplies two mat3's
   *
   * @param {mat3} out the receiving matrix
   * @param {mat3} a the first operand
   * @param {mat3} b the second operand
   * @returns {mat3} out
   */
  mat3.multiply = function (out, a, b) {
      var a00 = a[0], a01 = a[1], a02 = a[2],
          a10 = a[3], a11 = a[4], a12 = a[5],
          a20 = a[6], a21 = a[7], a22 = a[8],
  
          b00 = b[0], b01 = b[1], b02 = b[2],
          b10 = b[3], b11 = b[4], b12 = b[5],
          b20 = b[6], b21 = b[7], b22 = b[8];
  
      out[0] = b00 * a00 + b01 * a10 + b02 * a20;
      out[1] = b00 * a01 + b01 * a11 + b02 * a21;
      out[2] = b00 * a02 + b01 * a12 + b02 * a22;
  
      out[3] = b10 * a00 + b11 * a10 + b12 * a20;
      out[4] = b10 * a01 + b11 * a11 + b12 * a21;
      out[5] = b10 * a02 + b11 * a12 + b12 * a22;
  
      out[6] = b20 * a00 + b21 * a10 + b22 * a20;
      out[7] = b20 * a01 + b21 * a11 + b22 * a21;
      out[8] = b20 * a02 + b21 * a12 + b22 * a22;
      return out;
  };
  
  /**
   * Alias for {@link mat3.multiply}
   * @function
   */
  mat3.mul = mat3.multiply;
  
  /**
   * Translate a mat3 by the given vector
   *
   * @param {mat3} out the receiving matrix
   * @param {mat3} a the matrix to translate
   * @param {vec2} v vector to translate by
   * @returns {mat3} out
   */
  mat3.translate = function(out, a, v) {
      var a00 = a[0], a01 = a[1], a02 = a[2],
          a10 = a[3], a11 = a[4], a12 = a[5],
          a20 = a[6], a21 = a[7], a22 = a[8],
          x = v[0], y = v[1];
  
      out[0] = a00;
      out[1] = a01;
      out[2] = a02;
  
      out[3] = a10;
      out[4] = a11;
      out[5] = a12;
  
      out[6] = x * a00 + y * a10 + a20;
      out[7] = x * a01 + y * a11 + a21;
      out[8] = x * a02 + y * a12 + a22;
      return out;
  };
  
  /**
   * Rotates a mat3 by the given angle
   *
   * @param {mat3} out the receiving matrix
   * @param {mat3} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat3} out
   */
  mat3.rotate = function (out, a, rad) {
      var a00 = a[0], a01 = a[1], a02 = a[2],
          a10 = a[3], a11 = a[4], a12 = a[5],
          a20 = a[6], a21 = a[7], a22 = a[8],
  
          s = Math.sin(rad),
          c = Math.cos(rad);
  
      out[0] = c * a00 + s * a10;
      out[1] = c * a01 + s * a11;
      out[2] = c * a02 + s * a12;
  
      out[3] = c * a10 - s * a00;
      out[4] = c * a11 - s * a01;
      out[5] = c * a12 - s * a02;
  
      out[6] = a20;
      out[7] = a21;
      out[8] = a22;
      return out;
  };
  
  /**
   * Scales the mat3 by the dimensions in the given vec2
   *
   * @param {mat3} out the receiving matrix
   * @param {mat3} a the matrix to rotate
   * @param {vec2} v the vec2 to scale the matrix by
   * @returns {mat3} out
   **/
  mat3.scale = function(out, a, v) {
      var x = v[0], y = v[1];
  
      out[0] = x * a[0];
      out[1] = x * a[1];
      out[2] = x * a[2];
  
      out[3] = y * a[3];
      out[4] = y * a[4];
      out[5] = y * a[5];
  
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      return out;
  };
  
  /**
   * Creates a matrix from a vector translation
   * This is equivalent to (but much faster than):
   *
   *     mat3.identity(dest);
   *     mat3.translate(dest, dest, vec);
   *
   * @param {mat3} out mat3 receiving operation result
   * @param {vec2} v Translation vector
   * @returns {mat3} out
   */
  mat3.fromTranslation = function(out, v) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 1;
      out[5] = 0;
      out[6] = v[0];
      out[7] = v[1];
      out[8] = 1;
      return out;
  }
  
  /**
   * Creates a matrix from a given angle
   * This is equivalent to (but much faster than):
   *
   *     mat3.identity(dest);
   *     mat3.rotate(dest, dest, rad);
   *
   * @param {mat3} out mat3 receiving operation result
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat3} out
   */
  mat3.fromRotation = function(out, rad) {
      var s = Math.sin(rad), c = Math.cos(rad);
  
      out[0] = c;
      out[1] = s;
      out[2] = 0;
  
      out[3] = -s;
      out[4] = c;
      out[5] = 0;
  
      out[6] = 0;
      out[7] = 0;
      out[8] = 1;
      return out;
  }
  
  /**
   * Creates a matrix from a vector scaling
   * This is equivalent to (but much faster than):
   *
   *     mat3.identity(dest);
   *     mat3.scale(dest, dest, vec);
   *
   * @param {mat3} out mat3 receiving operation result
   * @param {vec2} v Scaling vector
   * @returns {mat3} out
   */
  mat3.fromScaling = function(out, v) {
      out[0] = v[0];
      out[1] = 0;
      out[2] = 0;
  
      out[3] = 0;
      out[4] = v[1];
      out[5] = 0;
  
      out[6] = 0;
      out[7] = 0;
      out[8] = 1;
      return out;
  }
  
  /**
   * Copies the values from a mat2d into a mat3
   *
   * @param {mat3} out the receiving matrix
   * @param {mat2d} a the matrix to copy
   * @returns {mat3} out
   **/
  mat3.fromMat2d = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = 0;
  
      out[3] = a[2];
      out[4] = a[3];
      out[5] = 0;
  
      out[6] = a[4];
      out[7] = a[5];
      out[8] = 1;
      return out;
  };
  
  /**
  * Calculates a 3x3 matrix from the given quaternion
  *
  * @param {mat3} out mat3 receiving operation result
  * @param {quat} q Quaternion to create matrix from
  *
  * @returns {mat3} out
  */
  mat3.fromQuat = function (out, q) {
      var x = q[0], y = q[1], z = q[2], w = q[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
  
          xx = x * x2,
          yx = y * x2,
          yy = y * y2,
          zx = z * x2,
          zy = z * y2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2;
  
      out[0] = 1 - yy - zz;
      out[3] = yx - wz;
      out[6] = zx + wy;
  
      out[1] = yx + wz;
      out[4] = 1 - xx - zz;
      out[7] = zy - wx;
  
      out[2] = zx - wy;
      out[5] = zy + wx;
      out[8] = 1 - xx - yy;
  
      return out;
  };
  
  /**
  * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix
  *
  * @param {mat3} out mat3 receiving operation result
  * @param {mat4} a Mat4 to derive the normal matrix from
  *
  * @returns {mat3} out
  */
  mat3.normalFromMat4 = function (out, a) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
  
          b00 = a00 * a11 - a01 * a10,
          b01 = a00 * a12 - a02 * a10,
          b02 = a00 * a13 - a03 * a10,
          b03 = a01 * a12 - a02 * a11,
          b04 = a01 * a13 - a03 * a11,
          b05 = a02 * a13 - a03 * a12,
          b06 = a20 * a31 - a21 * a30,
          b07 = a20 * a32 - a22 * a30,
          b08 = a20 * a33 - a23 * a30,
          b09 = a21 * a32 - a22 * a31,
          b10 = a21 * a33 - a23 * a31,
          b11 = a22 * a33 - a23 * a32,
  
          // Calculate the determinant
          det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  
      if (!det) { 
          return null; 
      }
      det = 1.0 / det;
  
      out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
      out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
      out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
  
      out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
      out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
      out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
  
      out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
      out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
      out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
  
      return out;
  };
  
  /**
   * Returns a string representation of a mat3
   *
   * @param {mat3} mat matrix to represent as a string
   * @returns {String} string representation of the matrix
   */
  mat3.str = function (a) {
      return 'mat3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + 
                      a[3] + ', ' + a[4] + ', ' + a[5] + ', ' + 
                      a[6] + ', ' + a[7] + ', ' + a[8] + ')';
  };
  
  /**
   * Returns Frobenius norm of a mat3
   *
   * @param {mat3} a the matrix to calculate Frobenius norm of
   * @returns {Number} Frobenius norm
   */
  mat3.frob = function (a) {
      return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2)))
  };
  
  
  module.exports = mat3;
  
  },{"./common.js":94}],98:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  var glMatrix = require("./common.js");
  
  /**
   * @class 4x4 Matrix
   * @name mat4
   */
  var mat4 = {};
  
  /**
   * Creates a new identity mat4
   *
   * @returns {mat4} a new 4x4 matrix
   */
  mat4.create = function() {
      var out = new glMatrix.ARRAY_TYPE(16);
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 1;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  };
  
  /**
   * Creates a new mat4 initialized with values from an existing matrix
   *
   * @param {mat4} a matrix to clone
   * @returns {mat4} a new 4x4 matrix
   */
  mat4.clone = function(a) {
      var out = new glMatrix.ARRAY_TYPE(16);
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      out[9] = a[9];
      out[10] = a[10];
      out[11] = a[11];
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
      return out;
  };
  
  /**
   * Copy the values from one mat4 to another
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the source matrix
   * @returns {mat4} out
   */
  mat4.copy = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[4] = a[4];
      out[5] = a[5];
      out[6] = a[6];
      out[7] = a[7];
      out[8] = a[8];
      out[9] = a[9];
      out[10] = a[10];
      out[11] = a[11];
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
      return out;
  };
  
  /**
   * Set a mat4 to the identity matrix
   *
   * @param {mat4} out the receiving matrix
   * @returns {mat4} out
   */
  mat4.identity = function(out) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 1;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  };
  
  /**
   * Transpose the values of a mat4
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the source matrix
   * @returns {mat4} out
   */
  mat4.transpose = function(out, a) {
      // If we are transposing ourselves we can skip a few steps but have to cache some values
      if (out === a) {
          var a01 = a[1], a02 = a[2], a03 = a[3],
              a12 = a[6], a13 = a[7],
              a23 = a[11];
  
          out[1] = a[4];
          out[2] = a[8];
          out[3] = a[12];
          out[4] = a01;
          out[6] = a[9];
          out[7] = a[13];
          out[8] = a02;
          out[9] = a12;
          out[11] = a[14];
          out[12] = a03;
          out[13] = a13;
          out[14] = a23;
      } else {
          out[0] = a[0];
          out[1] = a[4];
          out[2] = a[8];
          out[3] = a[12];
          out[4] = a[1];
          out[5] = a[5];
          out[6] = a[9];
          out[7] = a[13];
          out[8] = a[2];
          out[9] = a[6];
          out[10] = a[10];
          out[11] = a[14];
          out[12] = a[3];
          out[13] = a[7];
          out[14] = a[11];
          out[15] = a[15];
      }
      
      return out;
  };
  
  /**
   * Inverts a mat4
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the source matrix
   * @returns {mat4} out
   */
  mat4.invert = function(out, a) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
  
          b00 = a00 * a11 - a01 * a10,
          b01 = a00 * a12 - a02 * a10,
          b02 = a00 * a13 - a03 * a10,
          b03 = a01 * a12 - a02 * a11,
          b04 = a01 * a13 - a03 * a11,
          b05 = a02 * a13 - a03 * a12,
          b06 = a20 * a31 - a21 * a30,
          b07 = a20 * a32 - a22 * a30,
          b08 = a20 * a33 - a23 * a30,
          b09 = a21 * a32 - a22 * a31,
          b10 = a21 * a33 - a23 * a31,
          b11 = a22 * a33 - a23 * a32,
  
          // Calculate the determinant
          det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  
      if (!det) { 
          return null; 
      }
      det = 1.0 / det;
  
      out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
      out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
      out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
      out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
      out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
      out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
      out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
      out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
      out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
      out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
      out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
      out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
      out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
      out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
      out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
      out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  
      return out;
  };
  
  /**
   * Calculates the adjugate of a mat4
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the source matrix
   * @returns {mat4} out
   */
  mat4.adjoint = function(out, a) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
  
      out[0]  =  (a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22));
      out[1]  = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));
      out[2]  =  (a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12));
      out[3]  = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));
      out[4]  = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));
      out[5]  =  (a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22));
      out[6]  = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));
      out[7]  =  (a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12));
      out[8]  =  (a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21));
      out[9]  = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));
      out[10] =  (a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11));
      out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));
      out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));
      out[13] =  (a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21));
      out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));
      out[15] =  (a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11));
      return out;
  };
  
  /**
   * Calculates the determinant of a mat4
   *
   * @param {mat4} a the source matrix
   * @returns {Number} determinant of a
   */
  mat4.determinant = function (a) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
  
          b00 = a00 * a11 - a01 * a10,
          b01 = a00 * a12 - a02 * a10,
          b02 = a00 * a13 - a03 * a10,
          b03 = a01 * a12 - a02 * a11,
          b04 = a01 * a13 - a03 * a11,
          b05 = a02 * a13 - a03 * a12,
          b06 = a20 * a31 - a21 * a30,
          b07 = a20 * a32 - a22 * a30,
          b08 = a20 * a33 - a23 * a30,
          b09 = a21 * a32 - a22 * a31,
          b10 = a21 * a33 - a23 * a31,
          b11 = a22 * a33 - a23 * a32;
  
      // Calculate the determinant
      return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  };
  
  /**
   * Multiplies two mat4's
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the first operand
   * @param {mat4} b the second operand
   * @returns {mat4} out
   */
  mat4.multiply = function (out, a, b) {
      var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
          a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
          a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
          a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
  
      // Cache only the current line of the second matrix
      var b0  = b[0], b1 = b[1], b2 = b[2], b3 = b[3];  
      out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
      out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
      out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
      out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  
      b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
      out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
      out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
      out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
      out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  
      b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
      out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
      out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
      out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
      out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
  
      b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
      out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
      out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
      out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
      out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
      return out;
  };
  
  /**
   * Alias for {@link mat4.multiply}
   * @function
   */
  mat4.mul = mat4.multiply;
  
  /**
   * Translate a mat4 by the given vector
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to translate
   * @param {vec3} v vector to translate by
   * @returns {mat4} out
   */
  mat4.translate = function (out, a, v) {
      var x = v[0], y = v[1], z = v[2],
          a00, a01, a02, a03,
          a10, a11, a12, a13,
          a20, a21, a22, a23;
  
      if (a === out) {
          out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
          out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
          out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
          out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
      } else {
          a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
          a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
          a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
  
          out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03;
          out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13;
          out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23;
  
          out[12] = a00 * x + a10 * y + a20 * z + a[12];
          out[13] = a01 * x + a11 * y + a21 * z + a[13];
          out[14] = a02 * x + a12 * y + a22 * z + a[14];
          out[15] = a03 * x + a13 * y + a23 * z + a[15];
      }
  
      return out;
  };
  
  /**
   * Scales the mat4 by the dimensions in the given vec3
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to scale
   * @param {vec3} v the vec3 to scale the matrix by
   * @returns {mat4} out
   **/
  mat4.scale = function(out, a, v) {
      var x = v[0], y = v[1], z = v[2];
  
      out[0] = a[0] * x;
      out[1] = a[1] * x;
      out[2] = a[2] * x;
      out[3] = a[3] * x;
      out[4] = a[4] * y;
      out[5] = a[5] * y;
      out[6] = a[6] * y;
      out[7] = a[7] * y;
      out[8] = a[8] * z;
      out[9] = a[9] * z;
      out[10] = a[10] * z;
      out[11] = a[11] * z;
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
      return out;
  };
  
  /**
   * Rotates a mat4 by the given angle around the given axis
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @param {vec3} axis the axis to rotate around
   * @returns {mat4} out
   */
  mat4.rotate = function (out, a, rad, axis) {
      var x = axis[0], y = axis[1], z = axis[2],
          len = Math.sqrt(x * x + y * y + z * z),
          s, c, t,
          a00, a01, a02, a03,
          a10, a11, a12, a13,
          a20, a21, a22, a23,
          b00, b01, b02,
          b10, b11, b12,
          b20, b21, b22;
  
      if (Math.abs(len) < glMatrix.EPSILON) { return null; }
      
      len = 1 / len;
      x *= len;
      y *= len;
      z *= len;
  
      s = Math.sin(rad);
      c = Math.cos(rad);
      t = 1 - c;
  
      a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3];
      a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7];
      a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11];
  
      // Construct the elements of the rotation matrix
      b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s;
      b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s;
      b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c;
  
      // Perform rotation-specific matrix multiplication
      out[0] = a00 * b00 + a10 * b01 + a20 * b02;
      out[1] = a01 * b00 + a11 * b01 + a21 * b02;
      out[2] = a02 * b00 + a12 * b01 + a22 * b02;
      out[3] = a03 * b00 + a13 * b01 + a23 * b02;
      out[4] = a00 * b10 + a10 * b11 + a20 * b12;
      out[5] = a01 * b10 + a11 * b11 + a21 * b12;
      out[6] = a02 * b10 + a12 * b11 + a22 * b12;
      out[7] = a03 * b10 + a13 * b11 + a23 * b12;
      out[8] = a00 * b20 + a10 * b21 + a20 * b22;
      out[9] = a01 * b20 + a11 * b21 + a21 * b22;
      out[10] = a02 * b20 + a12 * b21 + a22 * b22;
      out[11] = a03 * b20 + a13 * b21 + a23 * b22;
  
      if (a !== out) { // If the source and destination differ, copy the unchanged last row
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
      return out;
  };
  
  /**
   * Rotates a matrix by the given angle around the X axis
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  mat4.rotateX = function (out, a, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad),
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11];
  
      if (a !== out) { // If the source and destination differ, copy the unchanged rows
          out[0]  = a[0];
          out[1]  = a[1];
          out[2]  = a[2];
          out[3]  = a[3];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      // Perform axis-specific matrix multiplication
      out[4] = a10 * c + a20 * s;
      out[5] = a11 * c + a21 * s;
      out[6] = a12 * c + a22 * s;
      out[7] = a13 * c + a23 * s;
      out[8] = a20 * c - a10 * s;
      out[9] = a21 * c - a11 * s;
      out[10] = a22 * c - a12 * s;
      out[11] = a23 * c - a13 * s;
      return out;
  };
  
  /**
   * Rotates a matrix by the given angle around the Y axis
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  mat4.rotateY = function (out, a, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad),
          a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a20 = a[8],
          a21 = a[9],
          a22 = a[10],
          a23 = a[11];
  
      if (a !== out) { // If the source and destination differ, copy the unchanged rows
          out[4]  = a[4];
          out[5]  = a[5];
          out[6]  = a[6];
          out[7]  = a[7];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      // Perform axis-specific matrix multiplication
      out[0] = a00 * c - a20 * s;
      out[1] = a01 * c - a21 * s;
      out[2] = a02 * c - a22 * s;
      out[3] = a03 * c - a23 * s;
      out[8] = a00 * s + a20 * c;
      out[9] = a01 * s + a21 * c;
      out[10] = a02 * s + a22 * c;
      out[11] = a03 * s + a23 * c;
      return out;
  };
  
  /**
   * Rotates a matrix by the given angle around the Z axis
   *
   * @param {mat4} out the receiving matrix
   * @param {mat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  mat4.rotateZ = function (out, a, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad),
          a00 = a[0],
          a01 = a[1],
          a02 = a[2],
          a03 = a[3],
          a10 = a[4],
          a11 = a[5],
          a12 = a[6],
          a13 = a[7];
  
      if (a !== out) { // If the source and destination differ, copy the unchanged last row
          out[8]  = a[8];
          out[9]  = a[9];
          out[10] = a[10];
          out[11] = a[11];
          out[12] = a[12];
          out[13] = a[13];
          out[14] = a[14];
          out[15] = a[15];
      }
  
      // Perform axis-specific matrix multiplication
      out[0] = a00 * c + a10 * s;
      out[1] = a01 * c + a11 * s;
      out[2] = a02 * c + a12 * s;
      out[3] = a03 * c + a13 * s;
      out[4] = a10 * c - a00 * s;
      out[5] = a11 * c - a01 * s;
      out[6] = a12 * c - a02 * s;
      out[7] = a13 * c - a03 * s;
      return out;
  };
  
  /**
   * Creates a matrix from a vector translation
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.translate(dest, dest, vec);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {vec3} v Translation vector
   * @returns {mat4} out
   */
  mat4.fromTranslation = function(out, v) {
      out[0] = 1;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = 1;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
      out[12] = v[0];
      out[13] = v[1];
      out[14] = v[2];
      out[15] = 1;
      return out;
  }
  
  /**
   * Creates a matrix from a vector scaling
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.scale(dest, dest, vec);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {vec3} v Scaling vector
   * @returns {mat4} out
   */
  mat4.fromScaling = function(out, v) {
      out[0] = v[0];
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = v[1];
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = v[2];
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  }
  
  /**
   * Creates a matrix from a given angle around a given axis
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.rotate(dest, dest, rad, axis);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {Number} rad the angle to rotate the matrix by
   * @param {vec3} axis the axis to rotate around
   * @returns {mat4} out
   */
  mat4.fromRotation = function(out, rad, axis) {
      var x = axis[0], y = axis[1], z = axis[2],
          len = Math.sqrt(x * x + y * y + z * z),
          s, c, t;
      
      if (Math.abs(len) < glMatrix.EPSILON) { return null; }
      
      len = 1 / len;
      x *= len;
      y *= len;
      z *= len;
      
      s = Math.sin(rad);
      c = Math.cos(rad);
      t = 1 - c;
      
      // Perform rotation-specific matrix multiplication
      out[0] = x * x * t + c;
      out[1] = y * x * t + z * s;
      out[2] = z * x * t - y * s;
      out[3] = 0;
      out[4] = x * y * t - z * s;
      out[5] = y * y * t + c;
      out[6] = z * y * t + x * s;
      out[7] = 0;
      out[8] = x * z * t + y * s;
      out[9] = y * z * t - x * s;
      out[10] = z * z * t + c;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  }
  
  /**
   * Creates a matrix from the given angle around the X axis
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.rotateX(dest, dest, rad);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  mat4.fromXRotation = function(out, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad);
      
      // Perform axis-specific matrix multiplication
      out[0]  = 1;
      out[1]  = 0;
      out[2]  = 0;
      out[3]  = 0;
      out[4] = 0;
      out[5] = c;
      out[6] = s;
      out[7] = 0;
      out[8] = 0;
      out[9] = -s;
      out[10] = c;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  }
  
  /**
   * Creates a matrix from the given angle around the Y axis
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.rotateY(dest, dest, rad);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  mat4.fromYRotation = function(out, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad);
      
      // Perform axis-specific matrix multiplication
      out[0]  = c;
      out[1]  = 0;
      out[2]  = -s;
      out[3]  = 0;
      out[4] = 0;
      out[5] = 1;
      out[6] = 0;
      out[7] = 0;
      out[8] = s;
      out[9] = 0;
      out[10] = c;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  }
  
  /**
   * Creates a matrix from the given angle around the Z axis
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.rotateZ(dest, dest, rad);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */
  mat4.fromZRotation = function(out, rad) {
      var s = Math.sin(rad),
          c = Math.cos(rad);
      
      // Perform axis-specific matrix multiplication
      out[0]  = c;
      out[1]  = s;
      out[2]  = 0;
      out[3]  = 0;
      out[4] = -s;
      out[5] = c;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 1;
      out[11] = 0;
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
      return out;
  }
  
  /**
   * Creates a matrix from a quaternion rotation and vector translation
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.translate(dest, vec);
   *     var quatMat = mat4.create();
   *     quat4.toMat4(quat, quatMat);
   *     mat4.multiply(dest, quatMat);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {quat4} q Rotation quaternion
   * @param {vec3} v Translation vector
   * @returns {mat4} out
   */
  mat4.fromRotationTranslation = function (out, q, v) {
      // Quaternion math
      var x = q[0], y = q[1], z = q[2], w = q[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
  
          xx = x * x2,
          xy = x * y2,
          xz = x * z2,
          yy = y * y2,
          yz = y * z2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2;
  
      out[0] = 1 - (yy + zz);
      out[1] = xy + wz;
      out[2] = xz - wy;
      out[3] = 0;
      out[4] = xy - wz;
      out[5] = 1 - (xx + zz);
      out[6] = yz + wx;
      out[7] = 0;
      out[8] = xz + wy;
      out[9] = yz - wx;
      out[10] = 1 - (xx + yy);
      out[11] = 0;
      out[12] = v[0];
      out[13] = v[1];
      out[14] = v[2];
      out[15] = 1;
      
      return out;
  };
  
  /**
   * Creates a matrix from a quaternion rotation, vector translation and vector scale
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.translate(dest, vec);
   *     var quatMat = mat4.create();
   *     quat4.toMat4(quat, quatMat);
   *     mat4.multiply(dest, quatMat);
   *     mat4.scale(dest, scale)
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {quat4} q Rotation quaternion
   * @param {vec3} v Translation vector
   * @param {vec3} s Scaling vector
   * @returns {mat4} out
   */
  mat4.fromRotationTranslationScale = function (out, q, v, s) {
      // Quaternion math
      var x = q[0], y = q[1], z = q[2], w = q[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
  
          xx = x * x2,
          xy = x * y2,
          xz = x * z2,
          yy = y * y2,
          yz = y * z2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2,
          sx = s[0],
          sy = s[1],
          sz = s[2];
  
      out[0] = (1 - (yy + zz)) * sx;
      out[1] = (xy + wz) * sx;
      out[2] = (xz - wy) * sx;
      out[3] = 0;
      out[4] = (xy - wz) * sy;
      out[5] = (1 - (xx + zz)) * sy;
      out[6] = (yz + wx) * sy;
      out[7] = 0;
      out[8] = (xz + wy) * sz;
      out[9] = (yz - wx) * sz;
      out[10] = (1 - (xx + yy)) * sz;
      out[11] = 0;
      out[12] = v[0];
      out[13] = v[1];
      out[14] = v[2];
      out[15] = 1;
      
      return out;
  };
  
  /**
   * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin
   * This is equivalent to (but much faster than):
   *
   *     mat4.identity(dest);
   *     mat4.translate(dest, vec);
   *     mat4.translate(dest, origin);
   *     var quatMat = mat4.create();
   *     quat4.toMat4(quat, quatMat);
   *     mat4.multiply(dest, quatMat);
   *     mat4.scale(dest, scale)
   *     mat4.translate(dest, negativeOrigin);
   *
   * @param {mat4} out mat4 receiving operation result
   * @param {quat4} q Rotation quaternion
   * @param {vec3} v Translation vector
   * @param {vec3} s Scaling vector
   * @param {vec3} o The origin vector around which to scale and rotate
   * @returns {mat4} out
   */
  mat4.fromRotationTranslationScaleOrigin = function (out, q, v, s, o) {
    // Quaternion math
    var x = q[0], y = q[1], z = q[2], w = q[3],
        x2 = x + x,
        y2 = y + y,
        z2 = z + z,
  
        xx = x * x2,
        xy = x * y2,
        xz = x * z2,
        yy = y * y2,
        yz = y * z2,
        zz = z * z2,
        wx = w * x2,
        wy = w * y2,
        wz = w * z2,
        
        sx = s[0],
        sy = s[1],
        sz = s[2],
  
        ox = o[0],
        oy = o[1],
        oz = o[2];
        
    out[0] = (1 - (yy + zz)) * sx;
    out[1] = (xy + wz) * sx;
    out[2] = (xz - wy) * sx;
    out[3] = 0;
    out[4] = (xy - wz) * sy;
    out[5] = (1 - (xx + zz)) * sy;
    out[6] = (yz + wx) * sy;
    out[7] = 0;
    out[8] = (xz + wy) * sz;
    out[9] = (yz - wx) * sz;
    out[10] = (1 - (xx + yy)) * sz;
    out[11] = 0;
    out[12] = v[0] + ox - (out[0] * ox + out[4] * oy + out[8] * oz);
    out[13] = v[1] + oy - (out[1] * ox + out[5] * oy + out[9] * oz);
    out[14] = v[2] + oz - (out[2] * ox + out[6] * oy + out[10] * oz);
    out[15] = 1;
          
    return out;
  };
  
  mat4.fromQuat = function (out, q) {
      var x = q[0], y = q[1], z = q[2], w = q[3],
          x2 = x + x,
          y2 = y + y,
          z2 = z + z,
  
          xx = x * x2,
          yx = y * x2,
          yy = y * y2,
          zx = z * x2,
          zy = z * y2,
          zz = z * z2,
          wx = w * x2,
          wy = w * y2,
          wz = w * z2;
  
      out[0] = 1 - yy - zz;
      out[1] = yx + wz;
      out[2] = zx - wy;
      out[3] = 0;
  
      out[4] = yx - wz;
      out[5] = 1 - xx - zz;
      out[6] = zy + wx;
      out[7] = 0;
  
      out[8] = zx + wy;
      out[9] = zy - wx;
      out[10] = 1 - xx - yy;
      out[11] = 0;
  
      out[12] = 0;
      out[13] = 0;
      out[14] = 0;
      out[15] = 1;
  
      return out;
  };
  
  /**
   * Generates a frustum matrix with the given bounds
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {Number} left Left bound of the frustum
   * @param {Number} right Right bound of the frustum
   * @param {Number} bottom Bottom bound of the frustum
   * @param {Number} top Top bound of the frustum
   * @param {Number} near Near bound of the frustum
   * @param {Number} far Far bound of the frustum
   * @returns {mat4} out
   */
  mat4.frustum = function (out, left, right, bottom, top, near, far) {
      var rl = 1 / (right - left),
          tb = 1 / (top - bottom),
          nf = 1 / (near - far);
      out[0] = (near * 2) * rl;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = (near * 2) * tb;
      out[6] = 0;
      out[7] = 0;
      out[8] = (right + left) * rl;
      out[9] = (top + bottom) * tb;
      out[10] = (far + near) * nf;
      out[11] = -1;
      out[12] = 0;
      out[13] = 0;
      out[14] = (far * near * 2) * nf;
      out[15] = 0;
      return out;
  };
  
  /**
   * Generates a perspective projection matrix with the given bounds
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {number} fovy Vertical field of view in radians
   * @param {number} aspect Aspect ratio. typically viewport width/height
   * @param {number} near Near bound of the frustum
   * @param {number} far Far bound of the frustum
   * @returns {mat4} out
   */
  mat4.perspective = function (out, fovy, aspect, near, far) {
      var f = 1.0 / Math.tan(fovy / 2),
          nf = 1 / (near - far);
      out[0] = f / aspect;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = f;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = (far + near) * nf;
      out[11] = -1;
      out[12] = 0;
      out[13] = 0;
      out[14] = (2 * far * near) * nf;
      out[15] = 0;
      return out;
  };
  
  /**
   * Generates a perspective projection matrix with the given field of view.
   * This is primarily useful for generating projection matrices to be used
   * with the still experiemental WebVR API.
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {number} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees
   * @param {number} near Near bound of the frustum
   * @param {number} far Far bound of the frustum
   * @returns {mat4} out
   */
  mat4.perspectiveFromFieldOfView = function (out, fov, near, far) {
      var upTan = Math.tan(fov.upDegrees * Math.PI/180.0),
          downTan = Math.tan(fov.downDegrees * Math.PI/180.0),
          leftTan = Math.tan(fov.leftDegrees * Math.PI/180.0),
          rightTan = Math.tan(fov.rightDegrees * Math.PI/180.0),
          xScale = 2.0 / (leftTan + rightTan),
          yScale = 2.0 / (upTan + downTan);
  
      out[0] = xScale;
      out[1] = 0.0;
      out[2] = 0.0;
      out[3] = 0.0;
      out[4] = 0.0;
      out[5] = yScale;
      out[6] = 0.0;
      out[7] = 0.0;
      out[8] = -((leftTan - rightTan) * xScale * 0.5);
      out[9] = ((upTan - downTan) * yScale * 0.5);
      out[10] = far / (near - far);
      out[11] = -1.0;
      out[12] = 0.0;
      out[13] = 0.0;
      out[14] = (far * near) / (near - far);
      out[15] = 0.0;
      return out;
  }
  
  /**
   * Generates a orthogonal projection matrix with the given bounds
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {number} left Left bound of the frustum
   * @param {number} right Right bound of the frustum
   * @param {number} bottom Bottom bound of the frustum
   * @param {number} top Top bound of the frustum
   * @param {number} near Near bound of the frustum
   * @param {number} far Far bound of the frustum
   * @returns {mat4} out
   */
  mat4.ortho = function (out, left, right, bottom, top, near, far) {
      var lr = 1 / (left - right),
          bt = 1 / (bottom - top),
          nf = 1 / (near - far);
      out[0] = -2 * lr;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      out[4] = 0;
      out[5] = -2 * bt;
      out[6] = 0;
      out[7] = 0;
      out[8] = 0;
      out[9] = 0;
      out[10] = 2 * nf;
      out[11] = 0;
      out[12] = (left + right) * lr;
      out[13] = (top + bottom) * bt;
      out[14] = (far + near) * nf;
      out[15] = 1;
      return out;
  };
  
  /**
   * Generates a look-at matrix with the given eye position, focal point, and up axis
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {vec3} eye Position of the viewer
   * @param {vec3} center Point the viewer is looking at
   * @param {vec3} up vec3 pointing up
   * @returns {mat4} out
   */
  mat4.lookAt = function (out, eye, center, up) {
      var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
          eyex = eye[0],
          eyey = eye[1],
          eyez = eye[2],
          upx = up[0],
          upy = up[1],
          upz = up[2],
          centerx = center[0],
          centery = center[1],
          centerz = center[2];
  
      if (Math.abs(eyex - centerx) < glMatrix.EPSILON &&
          Math.abs(eyey - centery) < glMatrix.EPSILON &&
          Math.abs(eyez - centerz) < glMatrix.EPSILON) {
          return mat4.identity(out);
      }
  
      z0 = eyex - centerx;
      z1 = eyey - centery;
      z2 = eyez - centerz;
  
      len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
      z0 *= len;
      z1 *= len;
      z2 *= len;
  
      x0 = upy * z2 - upz * z1;
      x1 = upz * z0 - upx * z2;
      x2 = upx * z1 - upy * z0;
      len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
      if (!len) {
          x0 = 0;
          x1 = 0;
          x2 = 0;
      } else {
          len = 1 / len;
          x0 *= len;
          x1 *= len;
          x2 *= len;
      }
  
      y0 = z1 * x2 - z2 * x1;
      y1 = z2 * x0 - z0 * x2;
      y2 = z0 * x1 - z1 * x0;
  
      len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
      if (!len) {
          y0 = 0;
          y1 = 0;
          y2 = 0;
      } else {
          len = 1 / len;
          y0 *= len;
          y1 *= len;
          y2 *= len;
      }
  
      out[0] = x0;
      out[1] = y0;
      out[2] = z0;
      out[3] = 0;
      out[4] = x1;
      out[5] = y1;
      out[6] = z1;
      out[7] = 0;
      out[8] = x2;
      out[9] = y2;
      out[10] = z2;
      out[11] = 0;
      out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
      out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
      out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
      out[15] = 1;
  
      return out;
  };
  
  /**
   * Returns a string representation of a mat4
   *
   * @param {mat4} mat matrix to represent as a string
   * @returns {String} string representation of the matrix
   */
  mat4.str = function (a) {
      return 'mat4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ', ' +
                      a[4] + ', ' + a[5] + ', ' + a[6] + ', ' + a[7] + ', ' +
                      a[8] + ', ' + a[9] + ', ' + a[10] + ', ' + a[11] + ', ' + 
                      a[12] + ', ' + a[13] + ', ' + a[14] + ', ' + a[15] + ')';
  };
  
  /**
   * Returns Frobenius norm of a mat4
   *
   * @param {mat4} a the matrix to calculate Frobenius norm of
   * @returns {Number} Frobenius norm
   */
  mat4.frob = function (a) {
      return(Math.sqrt(Math.pow(a[0], 2) + Math.pow(a[1], 2) + Math.pow(a[2], 2) + Math.pow(a[3], 2) + Math.pow(a[4], 2) + Math.pow(a[5], 2) + Math.pow(a[6], 2) + Math.pow(a[7], 2) + Math.pow(a[8], 2) + Math.pow(a[9], 2) + Math.pow(a[10], 2) + Math.pow(a[11], 2) + Math.pow(a[12], 2) + Math.pow(a[13], 2) + Math.pow(a[14], 2) + Math.pow(a[15], 2) ))
  };
  
  
  module.exports = mat4;
  
  },{"./common.js":94}],99:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  var glMatrix = require("./common.js");
  var mat3 = require("./mat3.js");
  var vec3 = require("./vec3.js");
  var vec4 = require("./vec4.js");
  
  /**
   * @class Quaternion
   * @name quat
   */
  var quat = {};
  
  /**
   * Creates a new identity quat
   *
   * @returns {quat} a new quaternion
   */
  quat.create = function() {
      var out = new glMatrix.ARRAY_TYPE(4);
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      return out;
  };
  
  /**
   * Sets a quaternion to represent the shortest rotation from one
   * vector to another.
   *
   * Both vectors are assumed to be unit length.
   *
   * @param {quat} out the receiving quaternion.
   * @param {vec3} a the initial vector
   * @param {vec3} b the destination vector
   * @returns {quat} out
   */
  quat.rotationTo = (function() {
      var tmpvec3 = vec3.create();
      var xUnitVec3 = vec3.fromValues(1,0,0);
      var yUnitVec3 = vec3.fromValues(0,1,0);
  
      return function(out, a, b) {
          var dot = vec3.dot(a, b);
          if (dot < -0.999999) {
              vec3.cross(tmpvec3, xUnitVec3, a);
              if (vec3.length(tmpvec3) < 0.000001)
                  vec3.cross(tmpvec3, yUnitVec3, a);
              vec3.normalize(tmpvec3, tmpvec3);
              quat.setAxisAngle(out, tmpvec3, Math.PI);
              return out;
          } else if (dot > 0.999999) {
              out[0] = 0;
              out[1] = 0;
              out[2] = 0;
              out[3] = 1;
              return out;
          } else {
              vec3.cross(tmpvec3, a, b);
              out[0] = tmpvec3[0];
              out[1] = tmpvec3[1];
              out[2] = tmpvec3[2];
              out[3] = 1 + dot;
              return quat.normalize(out, out);
          }
      };
  })();
  
  /**
   * Sets the specified quaternion with values corresponding to the given
   * axes. Each axis is a vec3 and is expected to be unit length and
   * perpendicular to all other specified axes.
   *
   * @param {vec3} view  the vector representing the viewing direction
   * @param {vec3} right the vector representing the local "right" direction
   * @param {vec3} up    the vector representing the local "up" direction
   * @returns {quat} out
   */
  quat.setAxes = (function() {
      var matr = mat3.create();
  
      return function(out, view, right, up) {
          matr[0] = right[0];
          matr[3] = right[1];
          matr[6] = right[2];
  
          matr[1] = up[0];
          matr[4] = up[1];
          matr[7] = up[2];
  
          matr[2] = -view[0];
          matr[5] = -view[1];
          matr[8] = -view[2];
  
          return quat.normalize(out, quat.fromMat3(out, matr));
      };
  })();
  
  /**
   * Creates a new quat initialized with values from an existing quaternion
   *
   * @param {quat} a quaternion to clone
   * @returns {quat} a new quaternion
   * @function
   */
  quat.clone = vec4.clone;
  
  /**
   * Creates a new quat initialized with the given values
   *
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @param {Number} w W component
   * @returns {quat} a new quaternion
   * @function
   */
  quat.fromValues = vec4.fromValues;
  
  /**
   * Copy the values from one quat to another
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the source quaternion
   * @returns {quat} out
   * @function
   */
  quat.copy = vec4.copy;
  
  /**
   * Set the components of a quat to the given values
   *
   * @param {quat} out the receiving quaternion
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @param {Number} w W component
   * @returns {quat} out
   * @function
   */
  quat.set = vec4.set;
  
  /**
   * Set a quat to the identity quaternion
   *
   * @param {quat} out the receiving quaternion
   * @returns {quat} out
   */
  quat.identity = function(out) {
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 1;
      return out;
  };
  
  /**
   * Sets a quat from the given angle and rotation axis,
   * then returns it.
   *
   * @param {quat} out the receiving quaternion
   * @param {vec3} axis the axis around which to rotate
   * @param {Number} rad the angle in radians
   * @returns {quat} out
   **/
  quat.setAxisAngle = function(out, axis, rad) {
      rad = rad * 0.5;
      var s = Math.sin(rad);
      out[0] = s * axis[0];
      out[1] = s * axis[1];
      out[2] = s * axis[2];
      out[3] = Math.cos(rad);
      return out;
  };
  
  /**
   * Adds two quat's
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @returns {quat} out
   * @function
   */
  quat.add = vec4.add;
  
  /**
   * Multiplies two quat's
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @returns {quat} out
   */
  quat.multiply = function(out, a, b) {
      var ax = a[0], ay = a[1], az = a[2], aw = a[3],
          bx = b[0], by = b[1], bz = b[2], bw = b[3];
  
      out[0] = ax * bw + aw * bx + ay * bz - az * by;
      out[1] = ay * bw + aw * by + az * bx - ax * bz;
      out[2] = az * bw + aw * bz + ax * by - ay * bx;
      out[3] = aw * bw - ax * bx - ay * by - az * bz;
      return out;
  };
  
  /**
   * Alias for {@link quat.multiply}
   * @function
   */
  quat.mul = quat.multiply;
  
  /**
   * Scales a quat by a scalar number
   *
   * @param {quat} out the receiving vector
   * @param {quat} a the vector to scale
   * @param {Number} b amount to scale the vector by
   * @returns {quat} out
   * @function
   */
  quat.scale = vec4.scale;
  
  /**
   * Rotates a quaternion by the given angle about the X axis
   *
   * @param {quat} out quat receiving operation result
   * @param {quat} a quat to rotate
   * @param {number} rad angle (in radians) to rotate
   * @returns {quat} out
   */
  quat.rotateX = function (out, a, rad) {
      rad *= 0.5; 
  
      var ax = a[0], ay = a[1], az = a[2], aw = a[3],
          bx = Math.sin(rad), bw = Math.cos(rad);
  
      out[0] = ax * bw + aw * bx;
      out[1] = ay * bw + az * bx;
      out[2] = az * bw - ay * bx;
      out[3] = aw * bw - ax * bx;
      return out;
  };
  
  /**
   * Rotates a quaternion by the given angle about the Y axis
   *
   * @param {quat} out quat receiving operation result
   * @param {quat} a quat to rotate
   * @param {number} rad angle (in radians) to rotate
   * @returns {quat} out
   */
  quat.rotateY = function (out, a, rad) {
      rad *= 0.5; 
  
      var ax = a[0], ay = a[1], az = a[2], aw = a[3],
          by = Math.sin(rad), bw = Math.cos(rad);
  
      out[0] = ax * bw - az * by;
      out[1] = ay * bw + aw * by;
      out[2] = az * bw + ax * by;
      out[3] = aw * bw - ay * by;
      return out;
  };
  
  /**
   * Rotates a quaternion by the given angle about the Z axis
   *
   * @param {quat} out quat receiving operation result
   * @param {quat} a quat to rotate
   * @param {number} rad angle (in radians) to rotate
   * @returns {quat} out
   */
  quat.rotateZ = function (out, a, rad) {
      rad *= 0.5; 
  
      var ax = a[0], ay = a[1], az = a[2], aw = a[3],
          bz = Math.sin(rad), bw = Math.cos(rad);
  
      out[0] = ax * bw + ay * bz;
      out[1] = ay * bw - ax * bz;
      out[2] = az * bw + aw * bz;
      out[3] = aw * bw - az * bz;
      return out;
  };
  
  /**
   * Calculates the W component of a quat from the X, Y, and Z components.
   * Assumes that quaternion is 1 unit in length.
   * Any existing W component will be ignored.
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a quat to calculate W component of
   * @returns {quat} out
   */
  quat.calculateW = function (out, a) {
      var x = a[0], y = a[1], z = a[2];
  
      out[0] = x;
      out[1] = y;
      out[2] = z;
      out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));
      return out;
  };
  
  /**
   * Calculates the dot product of two quat's
   *
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @returns {Number} dot product of a and b
   * @function
   */
  quat.dot = vec4.dot;
  
  /**
   * Performs a linear interpolation between two quat's
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {quat} out
   * @function
   */
  quat.lerp = vec4.lerp;
  
  /**
   * Performs a spherical linear interpolation between two quat
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {quat} out
   */
  quat.slerp = function (out, a, b, t) {
      // benchmarks:
      //    http://jsperf.com/quaternion-slerp-implementations
  
      var ax = a[0], ay = a[1], az = a[2], aw = a[3],
          bx = b[0], by = b[1], bz = b[2], bw = b[3];
  
      var        omega, cosom, sinom, scale0, scale1;
  
      // calc cosine
      cosom = ax * bx + ay * by + az * bz + aw * bw;
      // adjust signs (if necessary)
      if ( cosom < 0.0 ) {
          cosom = -cosom;
          bx = - bx;
          by = - by;
          bz = - bz;
          bw = - bw;
      }
      // calculate coefficients
      if ( (1.0 - cosom) > 0.000001 ) {
          // standard case (slerp)
          omega  = Math.acos(cosom);
          sinom  = Math.sin(omega);
          scale0 = Math.sin((1.0 - t) * omega) / sinom;
          scale1 = Math.sin(t * omega) / sinom;
      } else {        
          // "from" and "to" quaternions are very close 
          //  ... so we can do a linear interpolation
          scale0 = 1.0 - t;
          scale1 = t;
      }
      // calculate final values
      out[0] = scale0 * ax + scale1 * bx;
      out[1] = scale0 * ay + scale1 * by;
      out[2] = scale0 * az + scale1 * bz;
      out[3] = scale0 * aw + scale1 * bw;
      
      return out;
  };
  
  /**
   * Performs a spherical linear interpolation with two control points
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @param {quat} c the third operand
   * @param {quat} d the fourth operand
   * @param {Number} t interpolation amount
   * @returns {quat} out
   */
  quat.sqlerp = (function () {
    var temp1 = quat.create();
    var temp2 = quat.create();
    
    return function (out, a, b, c, d, t) {
      quat.slerp(temp1, a, d, t);
      quat.slerp(temp2, b, c, t);
      quat.slerp(out, temp1, temp2, 2 * t * (1 - t));
      
      return out;
    };
  }());
  
  /**
   * Calculates the inverse of a quat
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a quat to calculate inverse of
   * @returns {quat} out
   */
  quat.invert = function(out, a) {
      var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
          dot = a0*a0 + a1*a1 + a2*a2 + a3*a3,
          invDot = dot ? 1.0/dot : 0;
      
      // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
  
      out[0] = -a0*invDot;
      out[1] = -a1*invDot;
      out[2] = -a2*invDot;
      out[3] = a3*invDot;
      return out;
  };
  
  /**
   * Calculates the conjugate of a quat
   * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a quat to calculate conjugate of
   * @returns {quat} out
   */
  quat.conjugate = function (out, a) {
      out[0] = -a[0];
      out[1] = -a[1];
      out[2] = -a[2];
      out[3] = a[3];
      return out;
  };
  
  /**
   * Calculates the length of a quat
   *
   * @param {quat} a vector to calculate length of
   * @returns {Number} length of a
   * @function
   */
  quat.length = vec4.length;
  
  /**
   * Alias for {@link quat.length}
   * @function
   */
  quat.len = quat.length;
  
  /**
   * Calculates the squared length of a quat
   *
   * @param {quat} a vector to calculate squared length of
   * @returns {Number} squared length of a
   * @function
   */
  quat.squaredLength = vec4.squaredLength;
  
  /**
   * Alias for {@link quat.squaredLength}
   * @function
   */
  quat.sqrLen = quat.squaredLength;
  
  /**
   * Normalize a quat
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a quaternion to normalize
   * @returns {quat} out
   * @function
   */
  quat.normalize = vec4.normalize;
  
  /**
   * Creates a quaternion from the given 3x3 rotation matrix.
   *
   * NOTE: The resultant quaternion is not normalized, so you should be sure
   * to renormalize the quaternion yourself where necessary.
   *
   * @param {quat} out the receiving quaternion
   * @param {mat3} m rotation matrix
   * @returns {quat} out
   * @function
   */
  quat.fromMat3 = function(out, m) {
      // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
      // article "Quaternion Calculus and Fast Animation".
      var fTrace = m[0] + m[4] + m[8];
      var fRoot;
  
      if ( fTrace > 0.0 ) {
          // |w| > 1/2, may as well choose w > 1/2
          fRoot = Math.sqrt(fTrace + 1.0);  // 2w
          out[3] = 0.5 * fRoot;
          fRoot = 0.5/fRoot;  // 1/(4w)
          out[0] = (m[5]-m[7])*fRoot;
          out[1] = (m[6]-m[2])*fRoot;
          out[2] = (m[1]-m[3])*fRoot;
      } else {
          // |w| <= 1/2
          var i = 0;
          if ( m[4] > m[0] )
            i = 1;
          if ( m[8] > m[i*3+i] )
            i = 2;
          var j = (i+1)%3;
          var k = (i+2)%3;
          
          fRoot = Math.sqrt(m[i*3+i]-m[j*3+j]-m[k*3+k] + 1.0);
          out[i] = 0.5 * fRoot;
          fRoot = 0.5 / fRoot;
          out[3] = (m[j*3+k] - m[k*3+j]) * fRoot;
          out[j] = (m[j*3+i] + m[i*3+j]) * fRoot;
          out[k] = (m[k*3+i] + m[i*3+k]) * fRoot;
      }
      
      return out;
  };
  
  /**
   * Returns a string representation of a quatenion
   *
   * @param {quat} vec vector to represent as a string
   * @returns {String} string representation of the vector
   */
  quat.str = function (a) {
      return 'quat(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
  };
  
  module.exports = quat;
  
  },{"./common.js":94,"./mat3.js":97,"./vec3.js":101,"./vec4.js":102}],100:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  var glMatrix = require("./common.js");
  
  /**
   * @class 2 Dimensional Vector
   * @name vec2
   */
  var vec2 = {};
  
  /**
   * Creates a new, empty vec2
   *
   * @returns {vec2} a new 2D vector
   */
  vec2.create = function() {
      var out = new glMatrix.ARRAY_TYPE(2);
      out[0] = 0;
      out[1] = 0;
      return out;
  };
  
  /**
   * Creates a new vec2 initialized with values from an existing vector
   *
   * @param {vec2} a vector to clone
   * @returns {vec2} a new 2D vector
   */
  vec2.clone = function(a) {
      var out = new glMatrix.ARRAY_TYPE(2);
      out[0] = a[0];
      out[1] = a[1];
      return out;
  };
  
  /**
   * Creates a new vec2 initialized with the given values
   *
   * @param {Number} x X component
   * @param {Number} y Y component
   * @returns {vec2} a new 2D vector
   */
  vec2.fromValues = function(x, y) {
      var out = new glMatrix.ARRAY_TYPE(2);
      out[0] = x;
      out[1] = y;
      return out;
  };
  
  /**
   * Copy the values from one vec2 to another
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the source vector
   * @returns {vec2} out
   */
  vec2.copy = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      return out;
  };
  
  /**
   * Set the components of a vec2 to the given values
   *
   * @param {vec2} out the receiving vector
   * @param {Number} x X component
   * @param {Number} y Y component
   * @returns {vec2} out
   */
  vec2.set = function(out, x, y) {
      out[0] = x;
      out[1] = y;
      return out;
  };
  
  /**
   * Adds two vec2's
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {vec2} out
   */
  vec2.add = function(out, a, b) {
      out[0] = a[0] + b[0];
      out[1] = a[1] + b[1];
      return out;
  };
  
  /**
   * Subtracts vector b from vector a
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {vec2} out
   */
  vec2.subtract = function(out, a, b) {
      out[0] = a[0] - b[0];
      out[1] = a[1] - b[1];
      return out;
  };
  
  /**
   * Alias for {@link vec2.subtract}
   * @function
   */
  vec2.sub = vec2.subtract;
  
  /**
   * Multiplies two vec2's
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {vec2} out
   */
  vec2.multiply = function(out, a, b) {
      out[0] = a[0] * b[0];
      out[1] = a[1] * b[1];
      return out;
  };
  
  /**
   * Alias for {@link vec2.multiply}
   * @function
   */
  vec2.mul = vec2.multiply;
  
  /**
   * Divides two vec2's
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {vec2} out
   */
  vec2.divide = function(out, a, b) {
      out[0] = a[0] / b[0];
      out[1] = a[1] / b[1];
      return out;
  };
  
  /**
   * Alias for {@link vec2.divide}
   * @function
   */
  vec2.div = vec2.divide;
  
  /**
   * Returns the minimum of two vec2's
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {vec2} out
   */
  vec2.min = function(out, a, b) {
      out[0] = Math.min(a[0], b[0]);
      out[1] = Math.min(a[1], b[1]);
      return out;
  };
  
  /**
   * Returns the maximum of two vec2's
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {vec2} out
   */
  vec2.max = function(out, a, b) {
      out[0] = Math.max(a[0], b[0]);
      out[1] = Math.max(a[1], b[1]);
      return out;
  };
  
  /**
   * Scales a vec2 by a scalar number
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the vector to scale
   * @param {Number} b amount to scale the vector by
   * @returns {vec2} out
   */
  vec2.scale = function(out, a, b) {
      out[0] = a[0] * b;
      out[1] = a[1] * b;
      return out;
  };
  
  /**
   * Adds two vec2's after scaling the second operand by a scalar value
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @param {Number} scale the amount to scale b by before adding
   * @returns {vec2} out
   */
  vec2.scaleAndAdd = function(out, a, b, scale) {
      out[0] = a[0] + (b[0] * scale);
      out[1] = a[1] + (b[1] * scale);
      return out;
  };
  
  /**
   * Calculates the euclidian distance between two vec2's
   *
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {Number} distance between a and b
   */
  vec2.distance = function(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1];
      return Math.sqrt(x*x + y*y);
  };
  
  /**
   * Alias for {@link vec2.distance}
   * @function
   */
  vec2.dist = vec2.distance;
  
  /**
   * Calculates the squared euclidian distance between two vec2's
   *
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {Number} squared distance between a and b
   */
  vec2.squaredDistance = function(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1];
      return x*x + y*y;
  };
  
  /**
   * Alias for {@link vec2.squaredDistance}
   * @function
   */
  vec2.sqrDist = vec2.squaredDistance;
  
  /**
   * Calculates the length of a vec2
   *
   * @param {vec2} a vector to calculate length of
   * @returns {Number} length of a
   */
  vec2.length = function (a) {
      var x = a[0],
          y = a[1];
      return Math.sqrt(x*x + y*y);
  };
  
  /**
   * Alias for {@link vec2.length}
   * @function
   */
  vec2.len = vec2.length;
  
  /**
   * Calculates the squared length of a vec2
   *
   * @param {vec2} a vector to calculate squared length of
   * @returns {Number} squared length of a
   */
  vec2.squaredLength = function (a) {
      var x = a[0],
          y = a[1];
      return x*x + y*y;
  };
  
  /**
   * Alias for {@link vec2.squaredLength}
   * @function
   */
  vec2.sqrLen = vec2.squaredLength;
  
  /**
   * Negates the components of a vec2
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a vector to negate
   * @returns {vec2} out
   */
  vec2.negate = function(out, a) {
      out[0] = -a[0];
      out[1] = -a[1];
      return out;
  };
  
  /**
   * Returns the inverse of the components of a vec2
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a vector to invert
   * @returns {vec2} out
   */
  vec2.inverse = function(out, a) {
    out[0] = 1.0 / a[0];
    out[1] = 1.0 / a[1];
    return out;
  };
  
  /**
   * Normalize a vec2
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a vector to normalize
   * @returns {vec2} out
   */
  vec2.normalize = function(out, a) {
      var x = a[0],
          y = a[1];
      var len = x*x + y*y;
      if (len > 0) {
          //TODO: evaluate use of glm_invsqrt here?
          len = 1 / Math.sqrt(len);
          out[0] = a[0] * len;
          out[1] = a[1] * len;
      }
      return out;
  };
  
  /**
   * Calculates the dot product of two vec2's
   *
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {Number} dot product of a and b
   */
  vec2.dot = function (a, b) {
      return a[0] * b[0] + a[1] * b[1];
  };
  
  /**
   * Computes the cross product of two vec2's
   * Note that the cross product must by definition produce a 3D vector
   *
   * @param {vec3} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @returns {vec3} out
   */
  vec2.cross = function(out, a, b) {
      var z = a[0] * b[1] - a[1] * b[0];
      out[0] = out[1] = 0;
      out[2] = z;
      return out;
  };
  
  /**
   * Performs a linear interpolation between two vec2's
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the first operand
   * @param {vec2} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {vec2} out
   */
  vec2.lerp = function (out, a, b, t) {
      var ax = a[0],
          ay = a[1];
      out[0] = ax + t * (b[0] - ax);
      out[1] = ay + t * (b[1] - ay);
      return out;
  };
  
  /**
   * Generates a random vector with the given scale
   *
   * @param {vec2} out the receiving vector
   * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
   * @returns {vec2} out
   */
  vec2.random = function (out, scale) {
      scale = scale || 1.0;
      var r = glMatrix.RANDOM() * 2.0 * Math.PI;
      out[0] = Math.cos(r) * scale;
      out[1] = Math.sin(r) * scale;
      return out;
  };
  
  /**
   * Transforms the vec2 with a mat2
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the vector to transform
   * @param {mat2} m matrix to transform with
   * @returns {vec2} out
   */
  vec2.transformMat2 = function(out, a, m) {
      var x = a[0],
          y = a[1];
      out[0] = m[0] * x + m[2] * y;
      out[1] = m[1] * x + m[3] * y;
      return out;
  };
  
  /**
   * Transforms the vec2 with a mat2d
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the vector to transform
   * @param {mat2d} m matrix to transform with
   * @returns {vec2} out
   */
  vec2.transformMat2d = function(out, a, m) {
      var x = a[0],
          y = a[1];
      out[0] = m[0] * x + m[2] * y + m[4];
      out[1] = m[1] * x + m[3] * y + m[5];
      return out;
  };
  
  /**
   * Transforms the vec2 with a mat3
   * 3rd vector component is implicitly '1'
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the vector to transform
   * @param {mat3} m matrix to transform with
   * @returns {vec2} out
   */
  vec2.transformMat3 = function(out, a, m) {
      var x = a[0],
          y = a[1];
      out[0] = m[0] * x + m[3] * y + m[6];
      out[1] = m[1] * x + m[4] * y + m[7];
      return out;
  };
  
  /**
   * Transforms the vec2 with a mat4
   * 3rd vector component is implicitly '0'
   * 4th vector component is implicitly '1'
   *
   * @param {vec2} out the receiving vector
   * @param {vec2} a the vector to transform
   * @param {mat4} m matrix to transform with
   * @returns {vec2} out
   */
  vec2.transformMat4 = function(out, a, m) {
      var x = a[0], 
          y = a[1];
      out[0] = m[0] * x + m[4] * y + m[12];
      out[1] = m[1] * x + m[5] * y + m[13];
      return out;
  };
  
  /**
   * Perform some operation over an array of vec2s.
   *
   * @param {Array} a the array of vectors to iterate over
   * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
   * @param {Number} offset Number of elements to skip at the beginning of the array
   * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
   * @param {Function} fn Function to call for each vector in the array
   * @param {Object} [arg] additional argument to pass to fn
   * @returns {Array} a
   * @function
   */
  vec2.forEach = (function() {
      var vec = vec2.create();
  
      return function(a, stride, offset, count, fn, arg) {
          var i, l;
          if(!stride) {
              stride = 2;
          }
  
          if(!offset) {
              offset = 0;
          }
          
          if(count) {
              l = Math.min((count * stride) + offset, a.length);
          } else {
              l = a.length;
          }
  
          for(i = offset; i < l; i += stride) {
              vec[0] = a[i]; vec[1] = a[i+1];
              fn(vec, vec, arg);
              a[i] = vec[0]; a[i+1] = vec[1];
          }
          
          return a;
      };
  })();
  
  /**
   * Returns a string representation of a vector
   *
   * @param {vec2} vec vector to represent as a string
   * @returns {String} string representation of the vector
   */
  vec2.str = function (a) {
      return 'vec2(' + a[0] + ', ' + a[1] + ')';
  };
  
  module.exports = vec2;
  
  },{"./common.js":94}],101:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  var glMatrix = require("./common.js");
  
  /**
   * @class 3 Dimensional Vector
   * @name vec3
   */
  var vec3 = {};
  
  /**
   * Creates a new, empty vec3
   *
   * @returns {vec3} a new 3D vector
   */
  vec3.create = function() {
      var out = new glMatrix.ARRAY_TYPE(3);
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      return out;
  };
  
  /**
   * Creates a new vec3 initialized with values from an existing vector
   *
   * @param {vec3} a vector to clone
   * @returns {vec3} a new 3D vector
   */
  vec3.clone = function(a) {
      var out = new glMatrix.ARRAY_TYPE(3);
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      return out;
  };
  
  /**
   * Creates a new vec3 initialized with the given values
   *
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @returns {vec3} a new 3D vector
   */
  vec3.fromValues = function(x, y, z) {
      var out = new glMatrix.ARRAY_TYPE(3);
      out[0] = x;
      out[1] = y;
      out[2] = z;
      return out;
  };
  
  /**
   * Copy the values from one vec3 to another
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the source vector
   * @returns {vec3} out
   */
  vec3.copy = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      return out;
  };
  
  /**
   * Set the components of a vec3 to the given values
   *
   * @param {vec3} out the receiving vector
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @returns {vec3} out
   */
  vec3.set = function(out, x, y, z) {
      out[0] = x;
      out[1] = y;
      out[2] = z;
      return out;
  };
  
  /**
   * Adds two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  vec3.add = function(out, a, b) {
      out[0] = a[0] + b[0];
      out[1] = a[1] + b[1];
      out[2] = a[2] + b[2];
      return out;
  };
  
  /**
   * Subtracts vector b from vector a
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  vec3.subtract = function(out, a, b) {
      out[0] = a[0] - b[0];
      out[1] = a[1] - b[1];
      out[2] = a[2] - b[2];
      return out;
  };
  
  /**
   * Alias for {@link vec3.subtract}
   * @function
   */
  vec3.sub = vec3.subtract;
  
  /**
   * Multiplies two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  vec3.multiply = function(out, a, b) {
      out[0] = a[0] * b[0];
      out[1] = a[1] * b[1];
      out[2] = a[2] * b[2];
      return out;
  };
  
  /**
   * Alias for {@link vec3.multiply}
   * @function
   */
  vec3.mul = vec3.multiply;
  
  /**
   * Divides two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  vec3.divide = function(out, a, b) {
      out[0] = a[0] / b[0];
      out[1] = a[1] / b[1];
      out[2] = a[2] / b[2];
      return out;
  };
  
  /**
   * Alias for {@link vec3.divide}
   * @function
   */
  vec3.div = vec3.divide;
  
  /**
   * Returns the minimum of two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  vec3.min = function(out, a, b) {
      out[0] = Math.min(a[0], b[0]);
      out[1] = Math.min(a[1], b[1]);
      out[2] = Math.min(a[2], b[2]);
      return out;
  };
  
  /**
   * Returns the maximum of two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  vec3.max = function(out, a, b) {
      out[0] = Math.max(a[0], b[0]);
      out[1] = Math.max(a[1], b[1]);
      out[2] = Math.max(a[2], b[2]);
      return out;
  };
  
  /**
   * Scales a vec3 by a scalar number
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the vector to scale
   * @param {Number} b amount to scale the vector by
   * @returns {vec3} out
   */
  vec3.scale = function(out, a, b) {
      out[0] = a[0] * b;
      out[1] = a[1] * b;
      out[2] = a[2] * b;
      return out;
  };
  
  /**
   * Adds two vec3's after scaling the second operand by a scalar value
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @param {Number} scale the amount to scale b by before adding
   * @returns {vec3} out
   */
  vec3.scaleAndAdd = function(out, a, b, scale) {
      out[0] = a[0] + (b[0] * scale);
      out[1] = a[1] + (b[1] * scale);
      out[2] = a[2] + (b[2] * scale);
      return out;
  };
  
  /**
   * Calculates the euclidian distance between two vec3's
   *
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {Number} distance between a and b
   */
  vec3.distance = function(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1],
          z = b[2] - a[2];
      return Math.sqrt(x*x + y*y + z*z);
  };
  
  /**
   * Alias for {@link vec3.distance}
   * @function
   */
  vec3.dist = vec3.distance;
  
  /**
   * Calculates the squared euclidian distance between two vec3's
   *
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {Number} squared distance between a and b
   */
  vec3.squaredDistance = function(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1],
          z = b[2] - a[2];
      return x*x + y*y + z*z;
  };
  
  /**
   * Alias for {@link vec3.squaredDistance}
   * @function
   */
  vec3.sqrDist = vec3.squaredDistance;
  
  /**
   * Calculates the length of a vec3
   *
   * @param {vec3} a vector to calculate length of
   * @returns {Number} length of a
   */
  vec3.length = function (a) {
      var x = a[0],
          y = a[1],
          z = a[2];
      return Math.sqrt(x*x + y*y + z*z);
  };
  
  /**
   * Alias for {@link vec3.length}
   * @function
   */
  vec3.len = vec3.length;
  
  /**
   * Calculates the squared length of a vec3
   *
   * @param {vec3} a vector to calculate squared length of
   * @returns {Number} squared length of a
   */
  vec3.squaredLength = function (a) {
      var x = a[0],
          y = a[1],
          z = a[2];
      return x*x + y*y + z*z;
  };
  
  /**
   * Alias for {@link vec3.squaredLength}
   * @function
   */
  vec3.sqrLen = vec3.squaredLength;
  
  /**
   * Negates the components of a vec3
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a vector to negate
   * @returns {vec3} out
   */
  vec3.negate = function(out, a) {
      out[0] = -a[0];
      out[1] = -a[1];
      out[2] = -a[2];
      return out;
  };
  
  /**
   * Returns the inverse of the components of a vec3
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a vector to invert
   * @returns {vec3} out
   */
  vec3.inverse = function(out, a) {
    out[0] = 1.0 / a[0];
    out[1] = 1.0 / a[1];
    out[2] = 1.0 / a[2];
    return out;
  };
  
  /**
   * Normalize a vec3
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a vector to normalize
   * @returns {vec3} out
   */
  vec3.normalize = function(out, a) {
      var x = a[0],
          y = a[1],
          z = a[2];
      var len = x*x + y*y + z*z;
      if (len > 0) {
          //TODO: evaluate use of glm_invsqrt here?
          len = 1 / Math.sqrt(len);
          out[0] = a[0] * len;
          out[1] = a[1] * len;
          out[2] = a[2] * len;
      }
      return out;
  };
  
  /**
   * Calculates the dot product of two vec3's
   *
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {Number} dot product of a and b
   */
  vec3.dot = function (a, b) {
      return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
  };
  
  /**
   * Computes the cross product of two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  vec3.cross = function(out, a, b) {
      var ax = a[0], ay = a[1], az = a[2],
          bx = b[0], by = b[1], bz = b[2];
  
      out[0] = ay * bz - az * by;
      out[1] = az * bx - ax * bz;
      out[2] = ax * by - ay * bx;
      return out;
  };
  
  /**
   * Performs a linear interpolation between two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {vec3} out
   */
  vec3.lerp = function (out, a, b, t) {
      var ax = a[0],
          ay = a[1],
          az = a[2];
      out[0] = ax + t * (b[0] - ax);
      out[1] = ay + t * (b[1] - ay);
      out[2] = az + t * (b[2] - az);
      return out;
  };
  
  /**
   * Performs a hermite interpolation with two control points
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @param {vec3} c the third operand
   * @param {vec3} d the fourth operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {vec3} out
   */
  vec3.hermite = function (out, a, b, c, d, t) {
    var factorTimes2 = t * t,
        factor1 = factorTimes2 * (2 * t - 3) + 1,
        factor2 = factorTimes2 * (t - 2) + t,
        factor3 = factorTimes2 * (t - 1),
        factor4 = factorTimes2 * (3 - 2 * t);
    
    out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
    out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
    out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
    
    return out;
  };
  
  /**
   * Performs a bezier interpolation with two control points
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @param {vec3} c the third operand
   * @param {vec3} d the fourth operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {vec3} out
   */
  vec3.bezier = function (out, a, b, c, d, t) {
    var inverseFactor = 1 - t,
        inverseFactorTimesTwo = inverseFactor * inverseFactor,
        factorTimes2 = t * t,
        factor1 = inverseFactorTimesTwo * inverseFactor,
        factor2 = 3 * t * inverseFactorTimesTwo,
        factor3 = 3 * factorTimes2 * inverseFactor,
        factor4 = factorTimes2 * t;
    
    out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
    out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
    out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
    
    return out;
  };
  
  /**
   * Generates a random vector with the given scale
   *
   * @param {vec3} out the receiving vector
   * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
   * @returns {vec3} out
   */
  vec3.random = function (out, scale) {
      scale = scale || 1.0;
  
      var r = glMatrix.RANDOM() * 2.0 * Math.PI;
      var z = (glMatrix.RANDOM() * 2.0) - 1.0;
      var zScale = Math.sqrt(1.0-z*z) * scale;
  
      out[0] = Math.cos(r) * zScale;
      out[1] = Math.sin(r) * zScale;
      out[2] = z * scale;
      return out;
  };
  
  /**
   * Transforms the vec3 with a mat4.
   * 4th vector component is implicitly '1'
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the vector to transform
   * @param {mat4} m matrix to transform with
   * @returns {vec3} out
   */
  vec3.transformMat4 = function(out, a, m) {
      var x = a[0], y = a[1], z = a[2],
          w = m[3] * x + m[7] * y + m[11] * z + m[15];
      w = w || 1.0;
      out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
      out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
      out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
      return out;
  };
  
  /**
   * Transforms the vec3 with a mat3.
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the vector to transform
   * @param {mat4} m the 3x3 matrix to transform with
   * @returns {vec3} out
   */
  vec3.transformMat3 = function(out, a, m) {
      var x = a[0], y = a[1], z = a[2];
      out[0] = x * m[0] + y * m[3] + z * m[6];
      out[1] = x * m[1] + y * m[4] + z * m[7];
      out[2] = x * m[2] + y * m[5] + z * m[8];
      return out;
  };
  
  /**
   * Transforms the vec3 with a quat
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the vector to transform
   * @param {quat} q quaternion to transform with
   * @returns {vec3} out
   */
  vec3.transformQuat = function(out, a, q) {
      // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
  
      var x = a[0], y = a[1], z = a[2],
          qx = q[0], qy = q[1], qz = q[2], qw = q[3],
  
          // calculate quat * vec
          ix = qw * x + qy * z - qz * y,
          iy = qw * y + qz * x - qx * z,
          iz = qw * z + qx * y - qy * x,
          iw = -qx * x - qy * y - qz * z;
  
      // calculate result * inverse quat
      out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
      out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
      out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
      return out;
  };
  
  /**
   * Rotate a 3D vector around the x-axis
   * @param {vec3} out The receiving vec3
   * @param {vec3} a The vec3 point to rotate
   * @param {vec3} b The origin of the rotation
   * @param {Number} c The angle of rotation
   * @returns {vec3} out
   */
  vec3.rotateX = function(out, a, b, c){
     var p = [], r=[];
  	  //Translate point to the origin
  	  p[0] = a[0] - b[0];
  	  p[1] = a[1] - b[1];
    	p[2] = a[2] - b[2];
  
  	  //perform rotation
  	  r[0] = p[0];
  	  r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c);
  	  r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c);
  
  	  //translate to correct position
  	  out[0] = r[0] + b[0];
  	  out[1] = r[1] + b[1];
  	  out[2] = r[2] + b[2];
  
    	return out;
  };
  
  /**
   * Rotate a 3D vector around the y-axis
   * @param {vec3} out The receiving vec3
   * @param {vec3} a The vec3 point to rotate
   * @param {vec3} b The origin of the rotation
   * @param {Number} c The angle of rotation
   * @returns {vec3} out
   */
  vec3.rotateY = function(out, a, b, c){
    	var p = [], r=[];
    	//Translate point to the origin
    	p[0] = a[0] - b[0];
    	p[1] = a[1] - b[1];
    	p[2] = a[2] - b[2];
    
    	//perform rotation
    	r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c);
    	r[1] = p[1];
    	r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c);
    
    	//translate to correct position
    	out[0] = r[0] + b[0];
    	out[1] = r[1] + b[1];
    	out[2] = r[2] + b[2];
    
    	return out;
  };
  
  /**
   * Rotate a 3D vector around the z-axis
   * @param {vec3} out The receiving vec3
   * @param {vec3} a The vec3 point to rotate
   * @param {vec3} b The origin of the rotation
   * @param {Number} c The angle of rotation
   * @returns {vec3} out
   */
  vec3.rotateZ = function(out, a, b, c){
    	var p = [], r=[];
    	//Translate point to the origin
    	p[0] = a[0] - b[0];
    	p[1] = a[1] - b[1];
    	p[2] = a[2] - b[2];
    
    	//perform rotation
    	r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c);
    	r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c);
    	r[2] = p[2];
    
    	//translate to correct position
    	out[0] = r[0] + b[0];
    	out[1] = r[1] + b[1];
    	out[2] = r[2] + b[2];
    
    	return out;
  };
  
  /**
   * Perform some operation over an array of vec3s.
   *
   * @param {Array} a the array of vectors to iterate over
   * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
   * @param {Number} offset Number of elements to skip at the beginning of the array
   * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
   * @param {Function} fn Function to call for each vector in the array
   * @param {Object} [arg] additional argument to pass to fn
   * @returns {Array} a
   * @function
   */
  vec3.forEach = (function() {
      var vec = vec3.create();
  
      return function(a, stride, offset, count, fn, arg) {
          var i, l;
          if(!stride) {
              stride = 3;
          }
  
          if(!offset) {
              offset = 0;
          }
          
          if(count) {
              l = Math.min((count * stride) + offset, a.length);
          } else {
              l = a.length;
          }
  
          for(i = offset; i < l; i += stride) {
              vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
              fn(vec, vec, arg);
              a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
          }
          
          return a;
      };
  })();
  
  /**
   * Get the angle between two 3D vectors
   * @param {vec3} a The first operand
   * @param {vec3} b The second operand
   * @returns {Number} The angle in radians
   */
  vec3.angle = function(a, b) {
     
      var tempA = vec3.fromValues(a[0], a[1], a[2]);
      var tempB = vec3.fromValues(b[0], b[1], b[2]);
   
      vec3.normalize(tempA, tempA);
      vec3.normalize(tempB, tempB);
   
      var cosine = vec3.dot(tempA, tempB);
  
      if(cosine > 1.0){
          return 0;
      } else {
          return Math.acos(cosine);
      }     
  };
  
  /**
   * Returns a string representation of a vector
   *
   * @param {vec3} vec vector to represent as a string
   * @returns {String} string representation of the vector
   */
  vec3.str = function (a) {
      return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
  };
  
  module.exports = vec3;
  
  },{"./common.js":94}],102:[function(require,module,exports){
  /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
  
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.
  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE. */
  
  var glMatrix = require("./common.js");
  
  /**
   * @class 4 Dimensional Vector
   * @name vec4
   */
  var vec4 = {};
  
  /**
   * Creates a new, empty vec4
   *
   * @returns {vec4} a new 4D vector
   */
  vec4.create = function() {
      var out = new glMatrix.ARRAY_TYPE(4);
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
      return out;
  };
  
  /**
   * Creates a new vec4 initialized with values from an existing vector
   *
   * @param {vec4} a vector to clone
   * @returns {vec4} a new 4D vector
   */
  vec4.clone = function(a) {
      var out = new glMatrix.ARRAY_TYPE(4);
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      return out;
  };
  
  /**
   * Creates a new vec4 initialized with the given values
   *
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @param {Number} w W component
   * @returns {vec4} a new 4D vector
   */
  vec4.fromValues = function(x, y, z, w) {
      var out = new glMatrix.ARRAY_TYPE(4);
      out[0] = x;
      out[1] = y;
      out[2] = z;
      out[3] = w;
      return out;
  };
  
  /**
   * Copy the values from one vec4 to another
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the source vector
   * @returns {vec4} out
   */
  vec4.copy = function(out, a) {
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      return out;
  };
  
  /**
   * Set the components of a vec4 to the given values
   *
   * @param {vec4} out the receiving vector
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @param {Number} w W component
   * @returns {vec4} out
   */
  vec4.set = function(out, x, y, z, w) {
      out[0] = x;
      out[1] = y;
      out[2] = z;
      out[3] = w;
      return out;
  };
  
  /**
   * Adds two vec4's
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {vec4} out
   */
  vec4.add = function(out, a, b) {
      out[0] = a[0] + b[0];
      out[1] = a[1] + b[1];
      out[2] = a[2] + b[2];
      out[3] = a[3] + b[3];
      return out;
  };
  
  /**
   * Subtracts vector b from vector a
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {vec4} out
   */
  vec4.subtract = function(out, a, b) {
      out[0] = a[0] - b[0];
      out[1] = a[1] - b[1];
      out[2] = a[2] - b[2];
      out[3] = a[3] - b[3];
      return out;
  };
  
  /**
   * Alias for {@link vec4.subtract}
   * @function
   */
  vec4.sub = vec4.subtract;
  
  /**
   * Multiplies two vec4's
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {vec4} out
   */
  vec4.multiply = function(out, a, b) {
      out[0] = a[0] * b[0];
      out[1] = a[1] * b[1];
      out[2] = a[2] * b[2];
      out[3] = a[3] * b[3];
      return out;
  };
  
  /**
   * Alias for {@link vec4.multiply}
   * @function
   */
  vec4.mul = vec4.multiply;
  
  /**
   * Divides two vec4's
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {vec4} out
   */
  vec4.divide = function(out, a, b) {
      out[0] = a[0] / b[0];
      out[1] = a[1] / b[1];
      out[2] = a[2] / b[2];
      out[3] = a[3] / b[3];
      return out;
  };
  
  /**
   * Alias for {@link vec4.divide}
   * @function
   */
  vec4.div = vec4.divide;
  
  /**
   * Returns the minimum of two vec4's
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {vec4} out
   */
  vec4.min = function(out, a, b) {
      out[0] = Math.min(a[0], b[0]);
      out[1] = Math.min(a[1], b[1]);
      out[2] = Math.min(a[2], b[2]);
      out[3] = Math.min(a[3], b[3]);
      return out;
  };
  
  /**
   * Returns the maximum of two vec4's
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {vec4} out
   */
  vec4.max = function(out, a, b) {
      out[0] = Math.max(a[0], b[0]);
      out[1] = Math.max(a[1], b[1]);
      out[2] = Math.max(a[2], b[2]);
      out[3] = Math.max(a[3], b[3]);
      return out;
  };
  
  /**
   * Scales a vec4 by a scalar number
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the vector to scale
   * @param {Number} b amount to scale the vector by
   * @returns {vec4} out
   */
  vec4.scale = function(out, a, b) {
      out[0] = a[0] * b;
      out[1] = a[1] * b;
      out[2] = a[2] * b;
      out[3] = a[3] * b;
      return out;
  };
  
  /**
   * Adds two vec4's after scaling the second operand by a scalar value
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @param {Number} scale the amount to scale b by before adding
   * @returns {vec4} out
   */
  vec4.scaleAndAdd = function(out, a, b, scale) {
      out[0] = a[0] + (b[0] * scale);
      out[1] = a[1] + (b[1] * scale);
      out[2] = a[2] + (b[2] * scale);
      out[3] = a[3] + (b[3] * scale);
      return out;
  };
  
  /**
   * Calculates the euclidian distance between two vec4's
   *
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {Number} distance between a and b
   */
  vec4.distance = function(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1],
          z = b[2] - a[2],
          w = b[3] - a[3];
      return Math.sqrt(x*x + y*y + z*z + w*w);
  };
  
  /**
   * Alias for {@link vec4.distance}
   * @function
   */
  vec4.dist = vec4.distance;
  
  /**
   * Calculates the squared euclidian distance between two vec4's
   *
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {Number} squared distance between a and b
   */
  vec4.squaredDistance = function(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1],
          z = b[2] - a[2],
          w = b[3] - a[3];
      return x*x + y*y + z*z + w*w;
  };
  
  /**
   * Alias for {@link vec4.squaredDistance}
   * @function
   */
  vec4.sqrDist = vec4.squaredDistance;
  
  /**
   * Calculates the length of a vec4
   *
   * @param {vec4} a vector to calculate length of
   * @returns {Number} length of a
   */
  vec4.length = function (a) {
      var x = a[0],
          y = a[1],
          z = a[2],
          w = a[3];
      return Math.sqrt(x*x + y*y + z*z + w*w);
  };
  
  /**
   * Alias for {@link vec4.length}
   * @function
   */
  vec4.len = vec4.length;
  
  /**
   * Calculates the squared length of a vec4
   *
   * @param {vec4} a vector to calculate squared length of
   * @returns {Number} squared length of a
   */
  vec4.squaredLength = function (a) {
      var x = a[0],
          y = a[1],
          z = a[2],
          w = a[3];
      return x*x + y*y + z*z + w*w;
  };
  
  /**
   * Alias for {@link vec4.squaredLength}
   * @function
   */
  vec4.sqrLen = vec4.squaredLength;
  
  /**
   * Negates the components of a vec4
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a vector to negate
   * @returns {vec4} out
   */
  vec4.negate = function(out, a) {
      out[0] = -a[0];
      out[1] = -a[1];
      out[2] = -a[2];
      out[3] = -a[3];
      return out;
  };
  
  /**
   * Returns the inverse of the components of a vec4
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a vector to invert
   * @returns {vec4} out
   */
  vec4.inverse = function(out, a) {
    out[0] = 1.0 / a[0];
    out[1] = 1.0 / a[1];
    out[2] = 1.0 / a[2];
    out[3] = 1.0 / a[3];
    return out;
  };
  
  /**
   * Normalize a vec4
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a vector to normalize
   * @returns {vec4} out
   */
  vec4.normalize = function(out, a) {
      var x = a[0],
          y = a[1],
          z = a[2],
          w = a[3];
      var len = x*x + y*y + z*z + w*w;
      if (len > 0) {
          len = 1 / Math.sqrt(len);
          out[0] = x * len;
          out[1] = y * len;
          out[2] = z * len;
          out[3] = w * len;
      }
      return out;
  };
  
  /**
   * Calculates the dot product of two vec4's
   *
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {Number} dot product of a and b
   */
  vec4.dot = function (a, b) {
      return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
  };
  
  /**
   * Performs a linear interpolation between two vec4's
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {vec4} out
   */
  vec4.lerp = function (out, a, b, t) {
      var ax = a[0],
          ay = a[1],
          az = a[2],
          aw = a[3];
      out[0] = ax + t * (b[0] - ax);
      out[1] = ay + t * (b[1] - ay);
      out[2] = az + t * (b[2] - az);
      out[3] = aw + t * (b[3] - aw);
      return out;
  };
  
  /**
   * Generates a random vector with the given scale
   *
   * @param {vec4} out the receiving vector
   * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
   * @returns {vec4} out
   */
  vec4.random = function (out, scale) {
      scale = scale || 1.0;
  
      //TODO: This is a pretty awful way of doing this. Find something better.
      out[0] = glMatrix.RANDOM();
      out[1] = glMatrix.RANDOM();
      out[2] = glMatrix.RANDOM();
      out[3] = glMatrix.RANDOM();
      vec4.normalize(out, out);
      vec4.scale(out, out, scale);
      return out;
  };
  
  /**
   * Transforms the vec4 with a mat4.
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the vector to transform
   * @param {mat4} m matrix to transform with
   * @returns {vec4} out
   */
  vec4.transformMat4 = function(out, a, m) {
      var x = a[0], y = a[1], z = a[2], w = a[3];
      out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
      out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
      out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
      out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
      return out;
  };
  
  /**
   * Transforms the vec4 with a quat
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the vector to transform
   * @param {quat} q quaternion to transform with
   * @returns {vec4} out
   */
  vec4.transformQuat = function(out, a, q) {
      var x = a[0], y = a[1], z = a[2],
          qx = q[0], qy = q[1], qz = q[2], qw = q[3],
  
          // calculate quat * vec
          ix = qw * x + qy * z - qz * y,
          iy = qw * y + qz * x - qx * z,
          iz = qw * z + qx * y - qy * x,
          iw = -qx * x - qy * y - qz * z;
  
      // calculate result * inverse quat
      out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
      out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
      out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
      out[3] = a[3];
      return out;
  };
  
  /**
   * Perform some operation over an array of vec4s.
   *
   * @param {Array} a the array of vectors to iterate over
   * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
   * @param {Number} offset Number of elements to skip at the beginning of the array
   * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
   * @param {Function} fn Function to call for each vector in the array
   * @param {Object} [arg] additional argument to pass to fn
   * @returns {Array} a
   * @function
   */
  vec4.forEach = (function() {
      var vec = vec4.create();
  
      return function(a, stride, offset, count, fn, arg) {
          var i, l;
          if(!stride) {
              stride = 4;
          }
  
          if(!offset) {
              offset = 0;
          }
          
          if(count) {
              l = Math.min((count * stride) + offset, a.length);
          } else {
              l = a.length;
          }
  
          for(i = offset; i < l; i += stride) {
              vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3];
              fn(vec, vec, arg);
              a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3];
          }
          
          return a;
      };
  })();
  
  /**
   * Returns a string representation of a vector
   *
   * @param {vec4} vec vector to represent as a string
   * @returns {String} string representation of the vector
   */
  vec4.str = function (a) {
      return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')';
  };
  
  module.exports = vec4;
  
  },{"./common.js":94}],103:[function(require,module,exports){
  /**
   * Adds two quat's
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @returns {quat} out
   * @function
   */
  module.exports = require('gl-vec4/add')
  
  },{"gl-vec4/add":174}],104:[function(require,module,exports){
  module.exports = calculateW
  
  /**
   * Calculates the W component of a quat from the X, Y, and Z components.
   * Assumes that quaternion is 1 unit in length.
   * Any existing W component will be ignored.
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a quat to calculate W component of
   * @returns {quat} out
   */
  function calculateW (out, a) {
    var x = a[0], y = a[1], z = a[2]
  
    out[0] = x
    out[1] = y
    out[2] = z
    out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z))
    return out
  }
  
  },{}],105:[function(require,module,exports){
  /**
   * Creates a new quat initialized with values from an existing quaternion
   *
   * @param {quat} a quaternion to clone
   * @returns {quat} a new quaternion
   * @function
   */
  module.exports = require('gl-vec4/clone')
  
  },{"gl-vec4/clone":175}],106:[function(require,module,exports){
  module.exports = conjugate
  
  /**
   * Calculates the conjugate of a quat
   * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a quat to calculate conjugate of
   * @returns {quat} out
   */
  function conjugate (out, a) {
    out[0] = -a[0]
    out[1] = -a[1]
    out[2] = -a[2]
    out[3] = a[3]
    return out
  }
  
  },{}],107:[function(require,module,exports){
  /**
   * Copy the values from one quat to another
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the source quaternion
   * @returns {quat} out
   * @function
   */
  module.exports = require('gl-vec4/copy')
  
  },{"gl-vec4/copy":176}],108:[function(require,module,exports){
  module.exports = create
  
  /**
   * Creates a new identity quat
   *
   * @returns {quat} a new quaternion
   */
  function create () {
    var out = new Float32Array(4)
    out[0] = 0
    out[1] = 0
    out[2] = 0
    out[3] = 1
    return out
  }
  
  },{}],109:[function(require,module,exports){
  /**
   * Calculates the dot product of two quat's
   *
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @returns {Number} dot product of a and b
   * @function
   */
  module.exports = require('gl-vec4/dot')
  
  },{"gl-vec4/dot":177}],110:[function(require,module,exports){
  module.exports = fromMat3
  
  /**
   * Creates a quaternion from the given 3x3 rotation matrix.
   *
   * NOTE: The resultant quaternion is not normalized, so you should be sure
   * to renormalize the quaternion yourself where necessary.
   *
   * @param {quat} out the receiving quaternion
   * @param {mat3} m rotation matrix
   * @returns {quat} out
   * @function
   */
  function fromMat3 (out, m) {
    // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
    // article "Quaternion Calculus and Fast Animation".
    var fTrace = m[0] + m[4] + m[8]
    var fRoot
  
    if (fTrace > 0.0) {
      // |w| > 1/2, may as well choose w > 1/2
      fRoot = Math.sqrt(fTrace + 1.0)  // 2w
      out[3] = 0.5 * fRoot
      fRoot = 0.5 / fRoot  // 1/(4w)
      out[0] = (m[5] - m[7]) * fRoot
      out[1] = (m[6] - m[2]) * fRoot
      out[2] = (m[1] - m[3]) * fRoot
    } else {
      // |w| <= 1/2
      var i = 0
      if (m[4] > m[0]) {
        i = 1
      }
      if (m[8] > m[i * 3 + i]) {
        i = 2
      }
      var j = (i + 1) % 3
      var k = (i + 2) % 3
  
      fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0)
      out[i] = 0.5 * fRoot
      fRoot = 0.5 / fRoot
      out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot
      out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot
      out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot
    }
  
    return out
  }
  
  },{}],111:[function(require,module,exports){
  /**
   * Creates a new quat initialized with the given values
   *
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @param {Number} w W component
   * @returns {quat} a new quaternion
   * @function
   */
  module.exports = require('gl-vec4/fromValues')
  
  },{"gl-vec4/fromValues":178}],112:[function(require,module,exports){
  module.exports = identity
  
  /**
   * Set a quat to the identity quaternion
   *
   * @param {quat} out the receiving quaternion
   * @returns {quat} out
   */
  function identity (out) {
    out[0] = 0
    out[1] = 0
    out[2] = 0
    out[3] = 1
    return out
  }
  
  },{}],113:[function(require,module,exports){
  module.exports = {
    add: require('./add'),
    calculateW: require('./calculateW'),
    clone: require('./clone'),
    conjugate: require('./conjugate'),
    copy: require('./copy'),
    create: require('./create'),
    dot: require('./dot'),
    fromMat3: require('./fromMat3'),
    fromValues: require('./fromValues'),
    identity: require('./identity'),
    invert: require('./invert'),
    length: require('./length'),
    lerp: require('./lerp'),
    multiply: require('./multiply'),
    normalize: require('./normalize'),
    rotateX: require('./rotateX'),
    rotateY: require('./rotateY'),
    rotateZ: require('./rotateZ'),
    rotationTo: require('./rotationTo'),
    scale: require('./scale'),
    set: require('./set'),
    setAxes: require('./setAxes'),
    setAxisAngle: require('./setAxisAngle'),
    slerp: require('./slerp'),
    sqlerp: require('./sqlerp'),
    squaredLength: require('./squaredLength')
  }
  
  },{"./add":103,"./calculateW":104,"./clone":105,"./conjugate":106,"./copy":107,"./create":108,"./dot":109,"./fromMat3":110,"./fromValues":111,"./identity":112,"./invert":114,"./length":115,"./lerp":116,"./multiply":117,"./normalize":118,"./rotateX":119,"./rotateY":120,"./rotateZ":121,"./rotationTo":122,"./scale":123,"./set":124,"./setAxes":125,"./setAxisAngle":126,"./slerp":127,"./sqlerp":128,"./squaredLength":129}],114:[function(require,module,exports){
  module.exports = invert
  
  /**
   * Calculates the inverse of a quat
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a quat to calculate inverse of
   * @returns {quat} out
   */
  function invert (out, a) {
    var a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3],
      dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3,
      invDot = dot ? 1.0 / dot : 0
  
    // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0
  
    out[0] = -a0 * invDot
    out[1] = -a1 * invDot
    out[2] = -a2 * invDot
    out[3] = a3 * invDot
    return out
  }
  
  },{}],115:[function(require,module,exports){
  /**
   * Calculates the length of a quat
   *
   * @param {quat} a vector to calculate length of
   * @returns {Number} length of a
   * @function
   */
  module.exports = require('gl-vec4/length')
  
  },{"gl-vec4/length":179}],116:[function(require,module,exports){
  /**
   * Performs a linear interpolation between two quat's
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {quat} out
   * @function
   */
  module.exports = require('gl-vec4/lerp')
  
  },{"gl-vec4/lerp":180}],117:[function(require,module,exports){
  module.exports = multiply
  
  /**
   * Multiplies two quat's
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @returns {quat} out
   */
  function multiply (out, a, b) {
    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
      bx = b[0], by = b[1], bz = b[2], bw = b[3]
  
    out[0] = ax * bw + aw * bx + ay * bz - az * by
    out[1] = ay * bw + aw * by + az * bx - ax * bz
    out[2] = az * bw + aw * bz + ax * by - ay * bx
    out[3] = aw * bw - ax * bx - ay * by - az * bz
    return out
  }
  
  },{}],118:[function(require,module,exports){
  /**
   * Normalize a quat
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a quaternion to normalize
   * @returns {quat} out
   * @function
   */
  module.exports = require('gl-vec4/normalize')
  
  },{"gl-vec4/normalize":181}],119:[function(require,module,exports){
  module.exports = rotateX
  
  /**
   * Rotates a quaternion by the given angle about the X axis
   *
   * @param {quat} out quat receiving operation result
   * @param {quat} a quat to rotate
   * @param {number} rad angle (in radians) to rotate
   * @returns {quat} out
   */
  function rotateX (out, a, rad) {
    rad *= 0.5
  
    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
      bx = Math.sin(rad), bw = Math.cos(rad)
  
    out[0] = ax * bw + aw * bx
    out[1] = ay * bw + az * bx
    out[2] = az * bw - ay * bx
    out[3] = aw * bw - ax * bx
    return out
  }
  
  },{}],120:[function(require,module,exports){
  module.exports = rotateY
  
  /**
   * Rotates a quaternion by the given angle about the Y axis
   *
   * @param {quat} out quat receiving operation result
   * @param {quat} a quat to rotate
   * @param {number} rad angle (in radians) to rotate
   * @returns {quat} out
   */
  function rotateY (out, a, rad) {
    rad *= 0.5
  
    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
      by = Math.sin(rad), bw = Math.cos(rad)
  
    out[0] = ax * bw - az * by
    out[1] = ay * bw + aw * by
    out[2] = az * bw + ax * by
    out[3] = aw * bw - ay * by
    return out
  }
  
  },{}],121:[function(require,module,exports){
  module.exports = rotateZ
  
  /**
   * Rotates a quaternion by the given angle about the Z axis
   *
   * @param {quat} out quat receiving operation result
   * @param {quat} a quat to rotate
   * @param {number} rad angle (in radians) to rotate
   * @returns {quat} out
   */
  function rotateZ (out, a, rad) {
    rad *= 0.5
  
    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
      bz = Math.sin(rad), bw = Math.cos(rad)
  
    out[0] = ax * bw + ay * bz
    out[1] = ay * bw - ax * bz
    out[2] = az * bw + aw * bz
    out[3] = aw * bw - az * bz
    return out
  }
  
  },{}],122:[function(require,module,exports){
  var vecDot = require('gl-vec3/dot')
  var vecCross = require('gl-vec3/cross')
  var vecLength = require('gl-vec3/length')
  var vecNormalize = require('gl-vec3/normalize')
  
  var quatNormalize = require('./normalize')
  var quatAxisAngle = require('./setAxisAngle')
  
  module.exports = rotationTo
  
  var tmpvec3 = [0, 0, 0]
  var xUnitVec3 = [1, 0, 0]
  var yUnitVec3 = [0, 1, 0]
  
  /**
   * Sets a quaternion to represent the shortest rotation from one
   * vector to another.
   *
   * Both vectors are assumed to be unit length.
   *
   * @param {quat} out the receiving quaternion.
   * @param {vec3} a the initial vector
   * @param {vec3} b the destination vector
   * @returns {quat} out
   */
  function rotationTo (out, a, b) {
    var dot = vecDot(a, b)
    if (dot < -0.999999) {
      vecCross(tmpvec3, xUnitVec3, a)
      if (vecLength(tmpvec3) < 0.000001) {
        vecCross(tmpvec3, yUnitVec3, a)
      }
      vecNormalize(tmpvec3, tmpvec3)
      quatAxisAngle(out, tmpvec3, Math.PI)
      return out
    } else if (dot > 0.999999) {
      out[0] = 0
      out[1] = 0
      out[2] = 0
      out[3] = 1
      return out
    } else {
      vecCross(tmpvec3, a, b)
      out[0] = tmpvec3[0]
      out[1] = tmpvec3[1]
      out[2] = tmpvec3[2]
      out[3] = 1 + dot
      return quatNormalize(out, out)
    }
  }
  
  },{"./normalize":118,"./setAxisAngle":126,"gl-vec3/cross":146,"gl-vec3/dot":149,"gl-vec3/length":154,"gl-vec3/normalize":160}],123:[function(require,module,exports){
  /**
   * Scales a quat by a scalar number
   *
   * @param {quat} out the receiving vector
   * @param {quat} a the vector to scale
   * @param {Number} b amount to scale the vector by
   * @returns {quat} out
   * @function
   */
  module.exports = require('gl-vec4/scale')
  
  },{"gl-vec4/scale":182}],124:[function(require,module,exports){
  /**
   * Set the components of a quat to the given values
   *
   * @param {quat} out the receiving quaternion
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @param {Number} w W component
   * @returns {quat} out
   * @function
   */
  module.exports = require('gl-vec4/set')
  
  },{"gl-vec4/set":183}],125:[function(require,module,exports){
  var mat3create = require('gl-mat3/create')
  var fromMat3 = require('./fromMat3')
  var normalize = require('./normalize')
  
  module.exports = setAxes
  
  var matr = mat3create()
  
  /**
   * Sets the specified quaternion with values corresponding to the given
   * axes. Each axis is a vec3 and is expected to be unit length and
   * perpendicular to all other specified axes.
   *
   * @param {vec3} view  the vector representing the viewing direction
   * @param {vec3} right the vector representing the local "right" direction
   * @param {vec3} up    the vector representing the local "up" direction
   * @returns {quat} out
   */
  function setAxes (out, view, right, up) {
    matr[0] = right[0]
    matr[3] = right[1]
    matr[6] = right[2]
  
    matr[1] = up[0]
    matr[4] = up[1]
    matr[7] = up[2]
  
    matr[2] = -view[0]
    matr[5] = -view[1]
    matr[8] = -view[2]
  
    return normalize(out, fromMat3(out, matr))
  }
  
  },{"./fromMat3":110,"./normalize":118,"gl-mat3/create":68}],126:[function(require,module,exports){
  module.exports = setAxisAngle
  
  /**
   * Sets a quat from the given angle and rotation axis,
   * then returns it.
   *
   * @param {quat} out the receiving quaternion
   * @param {vec3} axis the axis around which to rotate
   * @param {Number} rad the angle in radians
   * @returns {quat} out
   **/
  function setAxisAngle (out, axis, rad) {
    rad = rad * 0.5
    var s = Math.sin(rad)
    out[0] = s * axis[0]
    out[1] = s * axis[1]
    out[2] = s * axis[2]
    out[3] = Math.cos(rad)
    return out
  }
  
  },{}],127:[function(require,module,exports){
  module.exports = slerp
  
  /**
   * Performs a spherical linear interpolation between two quat
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {quat} out
   */
  function slerp (out, a, b, t) {
    // benchmarks:
    //    http://jsperf.com/quaternion-slerp-implementations
  
    var ax = a[0], ay = a[1], az = a[2], aw = a[3],
      bx = b[0], by = b[1], bz = b[2], bw = b[3]
  
    var omega, cosom, sinom, scale0, scale1
  
    // calc cosine
    cosom = ax * bx + ay * by + az * bz + aw * bw
    // adjust signs (if necessary)
    if (cosom < 0.0) {
      cosom = -cosom
      bx = -bx
      by = -by
      bz = -bz
      bw = -bw
    }
    // calculate coefficients
    if ((1.0 - cosom) > 0.000001) {
      // standard case (slerp)
      omega = Math.acos(cosom)
      sinom = Math.sin(omega)
      scale0 = Math.sin((1.0 - t) * omega) / sinom
      scale1 = Math.sin(t * omega) / sinom
    } else {
      // "from" and "to" quaternions are very close
      //  ... so we can do a linear interpolation
      scale0 = 1.0 - t
      scale1 = t
    }
    // calculate final values
    out[0] = scale0 * ax + scale1 * bx
    out[1] = scale0 * ay + scale1 * by
    out[2] = scale0 * az + scale1 * bz
    out[3] = scale0 * aw + scale1 * bw
  
    return out
  }
  
  },{}],128:[function(require,module,exports){
  var slerp = require('./slerp')
  
  module.exports = sqlerp
  
  var temp1 = [0, 0, 0, 1]
  var temp2 = [0, 0, 0, 1]
  
  /**
   * Performs a spherical linear interpolation with two control points
   *
   * @param {quat} out the receiving quaternion
   * @param {quat} a the first operand
   * @param {quat} b the second operand
   * @param {quat} c the third operand
   * @param {quat} d the fourth operand
   * @param {Number} t interpolation amount
   * @returns {quat} out
   */
  function sqlerp (out, a, b, c, d, t) {
    slerp(temp1, a, d, t)
    slerp(temp2, b, c, t)
    slerp(out, temp1, temp2, 2 * t * (1 - t))
  
    return out
  }
  
  },{"./slerp":127}],129:[function(require,module,exports){
  /**
   * Calculates the squared length of a quat
   *
   * @param {quat} a vector to calculate squared length of
   * @returns {Number} squared length of a
   * @function
   */
  module.exports = require('gl-vec4/squaredLength')
  
  },{"gl-vec4/squaredLength":184}],130:[function(require,module,exports){
  'use strict'
  
  var createUniformWrapper   = require('./lib/create-uniforms')
  var createAttributeWrapper = require('./lib/create-attributes')
  var makeReflect            = require('./lib/reflect')
  var shaderCache            = require('./lib/shader-cache')
  var runtime                = require('./lib/runtime-reflect')
  
  //Shader object
  function Shader(gl) {
    this.gl         = gl
  
    //Default initialize these to null
    this._vref      = 
    this._fref      = 
    this._relink    =
    this.vertShader =
    this.fragShader =
    this.program    =
    this.attributes =
    this.uniforms   =
    this.types      = null
  }
  
  var proto = Shader.prototype
  
  proto.bind = function() {
    if(!this.program) {
      this._relink()
    }
    this.gl.useProgram(this.program)
  }
  
  proto.dispose = function() {
    if(this._fref) {
      this._fref.dispose()
    }
    if(this._vref) {
      this._vref.dispose()
    }
    this.attributes =
    this.types      =
    this.vertShader =
    this.fragShader =
    this.program    = 
    this._relink    = 
    this._fref      = 
    this._vref      = null
  }
  
  function compareAttributes(a, b) {
    if(a.name < b.name) {
      return -1
    }
    return 1
  }
  
  //Update export hook for glslify-live
  proto.update = function(
      vertSource
    , fragSource
    , uniforms
    , attributes) {
  
    //If only one object passed, assume glslify style output
    if(!fragSource || arguments.length === 1) {
      var obj = vertSource
      vertSource = obj.vertex
      fragSource = obj.fragment
      uniforms   = obj.uniforms
      attributes = obj.attributes
    }
  
    var wrapper = this
    var gl      = wrapper.gl
  
    //Compile vertex and fragment shaders
    var pvref = wrapper._vref
    wrapper._vref = shaderCache.shader(gl, gl.VERTEX_SHADER, vertSource)
    if(pvref) {
      pvref.dispose()
    }
    wrapper.vertShader = wrapper._vref.shader
    var pfref = this._fref
    wrapper._fref = shaderCache.shader(gl, gl.FRAGMENT_SHADER, fragSource)
    if(pfref) {
      pfref.dispose()
    }
    wrapper.fragShader = wrapper._fref.shader
    
    //If uniforms/attributes is not specified, use RT reflection
    if(!uniforms || !attributes) {
  
      //Create initial test program
      var testProgram = gl.createProgram()
      gl.attachShader(testProgram, wrapper.fragShader)
      gl.attachShader(testProgram, wrapper.vertShader)
      gl.linkProgram(testProgram)
      if(!gl.getProgramParameter(testProgram, gl.LINK_STATUS)) {
        var errLog = gl.getProgramInfoLog(testProgram)
        console.error('gl-shader: Error linking program:', errLog)
        throw new Error('gl-shader: Error linking program:' + errLog)
      }
      
      //Load data from runtime
      uniforms   = uniforms   || runtime.uniforms(gl, testProgram)
      attributes = attributes || runtime.attributes(gl, testProgram)
  
      //Release test program
      gl.deleteProgram(testProgram)
    }
  
    //Sort attributes lexicographically
    // overrides undefined WebGL behavior for attribute locations
    attributes = attributes.slice()
    attributes.sort(compareAttributes)
  
    //Convert attribute types, read out locations
    var attributeUnpacked  = []
    var attributeNames     = []
    var attributeLocations = []
    for(var i=0; i<attributes.length; ++i) {
      var attr = attributes[i]
      if(attr.type.indexOf('mat') >= 0) {
        var size = attr.type.charAt(attr.type.length-1)|0
        var locVector = new Array(size)
        for(var j=0; j<size; ++j) {
          locVector[j] = attributeLocations.length
          attributeNames.push(attr.name + '[' + j + ']')
          if(typeof attr.location === 'number') {
            attributeLocations.push(attr.location + j)
          } else if(Array.isArray(attr.location) && 
                    attr.location.length === size &&
                    typeof attr.location[j] === 'number') {
            attributeLocations.push(attr.location[j]|0)
          } else {
            attributeLocations.push(-1)
          }
        }
        attributeUnpacked.push({
          name: attr.name,
          type: attr.type,
          locations: locVector
        })
      } else {
        attributeUnpacked.push({
          name: attr.name,
          type: attr.type,
          locations: [ attributeLocations.length ]
        })
        attributeNames.push(attr.name)
        if(typeof attr.location === 'number') {
          attributeLocations.push(attr.location|0)
        } else {
          attributeLocations.push(-1)
        }
      }
    }
  
    //For all unspecified attributes, assign them lexicographically min attribute
    var curLocation = 0
    for(var i=0; i<attributeLocations.length; ++i) {
      if(attributeLocations[i] < 0) {
        while(attributeLocations.indexOf(curLocation) >= 0) {
          curLocation += 1
        }
        attributeLocations[i] = curLocation
      }
    }
  
    //Rebuild program and recompute all uniform locations
    var uniformLocations = new Array(uniforms.length)
    function relink() {
      wrapper.program = shaderCache.program(
          gl
        , wrapper._vref
        , wrapper._fref
        , attributeNames
        , attributeLocations)
  
      for(var i=0; i<uniforms.length; ++i) {
        uniformLocations[i] = gl.getUniformLocation(
            wrapper.program
          , uniforms[i].name)
      }
    }
  
    //Perform initial linking, reuse program used for reflection
    relink()
  
    //Save relinking procedure, defer until runtime
    wrapper._relink = relink
  
    //Generate type info
    wrapper.types = {
      uniforms:   makeReflect(uniforms),
      attributes: makeReflect(attributes)
    }
  
    //Generate attribute wrappers
    wrapper.attributes = createAttributeWrapper(
        gl
      , wrapper
      , attributeUnpacked
      , attributeLocations)
  
    //Generate uniform wrappers
    Object.defineProperty(wrapper, 'uniforms', createUniformWrapper(
        gl
      , wrapper
      , uniforms
      , uniformLocations))
  }
  
  //Compiles and links a shader program with the given attribute and vertex list
  function createShader(
      gl
    , vertSource
    , fragSource
    , uniforms
    , attributes) {
  
    var shader = new Shader(gl)
  
    shader.update(
        vertSource
      , fragSource
      , uniforms
      , attributes)
  
    return shader
  }
  
  module.exports = createShader
  },{"./lib/create-attributes":131,"./lib/create-uniforms":132,"./lib/reflect":133,"./lib/runtime-reflect":134,"./lib/shader-cache":135}],131:[function(require,module,exports){
  'use strict'
  
  module.exports = createAttributeWrapper
  
  function ShaderAttribute(
      gl
    , wrapper
    , index
    , locations
    , dimension
    , constFunc) {
    this._gl        = gl
    this._wrapper   = wrapper
    this._index     = index
    this._locations = locations
    this._dimension = dimension
    this._constFunc = constFunc
  }
  
  var proto = ShaderAttribute.prototype
  
  proto.pointer = function setAttribPointer(
      type
    , normalized
    , stride
    , offset) {
  
    var self      = this
    var gl        = self._gl
    var location  = self._locations[self._index]
  
    gl.vertexAttribPointer(
        location
      , self._dimension
      , type || gl.FLOAT
      , !!normalized
      , stride || 0
      , offset || 0)
    gl.enableVertexAttribArray(location)
  }
  
  proto.set = function(x0, x1, x2, x3) {
    return this._constFunc(this._locations[this._index], x0, x1, x2, x3)
  }
  
  Object.defineProperty(proto, 'location', {
    get: function() {
      return this._locations[this._index]
    }
    , set: function(v) {
      if(v !== this._locations[this._index]) {
        this._locations[this._index] = v|0
        this._wrapper.program = null
      }
      return v|0
    }
  })
  
  //Adds a vector attribute to obj
  function addVectorAttribute(
      gl
    , wrapper
    , index
    , locations
    , dimension
    , obj
    , name) {
  
    //Construct constant function
    var constFuncArgs = [ 'gl', 'v' ]
    var varNames = []
    for(var i=0; i<dimension; ++i) {
      constFuncArgs.push('x'+i)
      varNames.push('x'+i)
    }
    constFuncArgs.push(
      'if(x0.length===void 0){return gl.vertexAttrib' +
      dimension + 'f(v,' +
      varNames.join() +
      ')}else{return gl.vertexAttrib' +
      dimension +
      'fv(v,x0)}')
    var constFunc = Function.apply(null, constFuncArgs)
  
    //Create attribute wrapper
    var attr = new ShaderAttribute(
        gl
      , wrapper
      , index
      , locations
      , dimension
      , constFunc)
  
    //Create accessor
    Object.defineProperty(obj, name, {
      set: function(x) {
        gl.disableVertexAttribArray(locations[index])
        constFunc(gl, locations[index], x)
        return x
      }
      , get: function() {
        return attr
      }
      , enumerable: true
    })
  }
  
  function addMatrixAttribute(
      gl
    , wrapper
    , index
    , locations
    , dimension
    , obj
    , name) {
  
    var parts = new Array(dimension)
    var attrs = new Array(dimension)
    for(var i=0; i<dimension; ++i) {
      addVectorAttribute(
          gl
        , wrapper
        , index[i]
        , locations
        , dimension
        , parts
        , i)
      attrs[i] = parts[i]
    }
  
    Object.defineProperty(parts, 'location', {
      set: function(v) {
        if(Array.isArray(v)) {
          for(var i=0; i<dimension; ++i) {
            attrs[i].location = v[i]
          }
        } else {
          for(var i=0; i<dimension; ++i) {
            attrs[i].location = v + i
          }
        }
        return v
      }
      , get: function() {
        var result = new Array(dimension)
        for(var i=0; i<dimension; ++i) {
          result[i] = locations[index[i]]
        }
        return result
      }
      , enumerable: true
    })
  
    parts.pointer = function(type, normalized, stride, offset) {
      type       = type || gl.FLOAT
      normalized = !!normalized
      stride     = stride || (dimension * dimension)
      offset     = offset || 0
      for(var i=0; i<dimension; ++i) {
        var location = locations[index[i]]
        gl.vertexAttribPointer(
              location
            , dimension
            , type
            , normalized
            , stride
            , offset + i * dimension)
        gl.enableVertexAttribArray(location)
      }
    }
  
    var scratch = new Array(dimension)
    var vertexAttrib = gl['vertexAttrib' + dimension + 'fv']
  
    Object.defineProperty(obj, name, {
      set: function(x) {
        for(var i=0; i<dimension; ++i) {
          var loc = locations[index[i]]
          gl.disableVertexAttribArray(loc)
          if(Array.isArray(x[0])) {
            vertexAttrib.call(gl, loc, x[i])
          } else {
            for(var j=0; j<dimension; ++j) {
              scratch[j] = x[dimension*i + j]
            }
            vertexAttrib.call(gl, loc, scratch)
          }
        }
        return x
      }
      , get: function() {
        return parts
      }
      , enumerable: true
    })
  }
  
  //Create shims for attributes
  function createAttributeWrapper(
      gl
    , wrapper
    , attributes
    , locations) {
  
    var obj = {}
    for(var i=0, n=attributes.length; i<n; ++i) {
  
      var a = attributes[i]
      var name = a.name
      var type = a.type
      var locs = a.locations
  
      switch(type) {
        case 'bool':
        case 'int':
        case 'float':
          addVectorAttribute(
              gl
            , wrapper
            , locs[0]
            , locations
            , 1
            , obj
            , name)
        break
  
        default:
          if(type.indexOf('vec') >= 0) {
            var d = type.charCodeAt(type.length-1) - 48
            if(d < 2 || d > 4) {
              throw new Error('gl-shader: Invalid data type for attribute ' + name + ': ' + type)
            }
            addVectorAttribute(
                gl
              , wrapper
              , locs[0]
              , locations
              , d
              , obj
              , name)
          } else if(type.indexOf('mat') >= 0) {
            var d = type.charCodeAt(type.length-1) - 48
            if(d < 2 || d > 4) {
              throw new Error('gl-shader: Invalid data type for attribute ' + name + ': ' + type)
            }
            addMatrixAttribute(
                gl
              , wrapper
              , locs
              , locations
              , d
              , obj
              , name)
          } else {
            throw new Error('gl-shader: Unknown data type for attribute ' + name + ': ' + type)
          }
        break
      }
    }
    return obj
  }
  
  },{}],132:[function(require,module,exports){
  'use strict'
  
  var coallesceUniforms = require('./reflect')
  
  module.exports = createUniformWrapper
  
  //Binds a function and returns a value
  function identity(x) {
    var c = new Function('y', 'return function(){return y}')
    return c(x)
  }
  
  function makeVector(length, fill) {
    var result = new Array(length)
    for(var i=0; i<length; ++i) {
      result[i] = fill
    }
    return result
  }
  
  //Create shims for uniforms
  function createUniformWrapper(gl, wrapper, uniforms, locations) {
  
    function makeGetter(index) {
      var proc = new Function(
          'gl'
        , 'wrapper'
        , 'locations'
        , 'return function(){return gl.getUniform(wrapper.program,locations[' + index + '])}') 
      return proc(gl, wrapper, locations)
    }
  
    function makePropSetter(path, index, type) {
      switch(type) {
        case 'bool':
        case 'int':
        case 'sampler2D':
        case 'samplerCube':
          return 'gl.uniform1i(locations[' + index + '],obj' + path + ')'
        case 'float':
          return 'gl.uniform1f(locations[' + index + '],obj' + path + ')'
        default:
          var vidx = type.indexOf('vec')
          if(0 <= vidx && vidx <= 1 && type.length === 4 + vidx) {
            var d = type.charCodeAt(type.length-1) - 48
            if(d < 2 || d > 4) {
              throw new Error('gl-shader: Invalid data type')
            }
            switch(type.charAt(0)) {
              case 'b':
              case 'i':
                return 'gl.uniform' + d + 'iv(locations[' + index + '],obj' + path + ')'
              case 'v':
                return 'gl.uniform' + d + 'fv(locations[' + index + '],obj' + path + ')'
              default:
                throw new Error('gl-shader: Unrecognized data type for vector ' + name + ': ' + type)
            }
          } else if(type.indexOf('mat') === 0 && type.length === 4) {
            var d = type.charCodeAt(type.length-1) - 48
            if(d < 2 || d > 4) {
              throw new Error('gl-shader: Invalid uniform dimension type for matrix ' + name + ': ' + type)
            }
            return 'gl.uniformMatrix' + d + 'fv(locations[' + index + '],false,obj' + path + ')'
          } else {
            throw new Error('gl-shader: Unknown uniform data type for ' + name + ': ' + type)
          }
        break
      }
    }
  
    function enumerateIndices(prefix, type) {
      if(typeof type !== 'object') {
        return [ [prefix, type] ]
      }
      var indices = []
      for(var id in type) {
        var prop = type[id]
        var tprefix = prefix
        if(parseInt(id) + '' === id) {
          tprefix += '[' + id + ']'
        } else {
          tprefix += '.' + id
        }
        if(typeof prop === 'object') {
          indices.push.apply(indices, enumerateIndices(tprefix, prop))
        } else {
          indices.push([tprefix, prop])
        }
      }
      return indices
    }
  
    function makeSetter(type) {
      var code = [ 'return function updateProperty(obj){' ]
      var indices = enumerateIndices('', type)
      for(var i=0; i<indices.length; ++i) {
        var item = indices[i]
        var path = item[0]
        var idx  = item[1]
        if(locations[idx]) {
          code.push(makePropSetter(path, idx, uniforms[idx].type))
        }
      }
      code.push('return obj}')
      var proc = new Function('gl', 'locations', code.join('\n'))
      return proc(gl, locations)
    }
  
    function defaultValue(type) {
      switch(type) {
        case 'bool':
          return false
        case 'int':
        case 'sampler2D':
        case 'samplerCube':
          return 0
        case 'float':
          return 0.0
        default:
          var vidx = type.indexOf('vec')
          if(0 <= vidx && vidx <= 1 && type.length === 4 + vidx) {
            var d = type.charCodeAt(type.length-1) - 48
            if(d < 2 || d > 4) {
              throw new Error('gl-shader: Invalid data type')
            }
            if(type.charAt(0) === 'b') {
              return makeVector(d, false)
            }
            return makeVector(d, 0)
          } else if(type.indexOf('mat') === 0 && type.length === 4) {
            var d = type.charCodeAt(type.length-1) - 48
            if(d < 2 || d > 4) {
              throw new Error('gl-shader: Invalid uniform dimension type for matrix ' + name + ': ' + type)
            }
            return makeVector(d*d, 0)
          } else {
            throw new Error('gl-shader: Unknown uniform data type for ' + name + ': ' + type)
          }
        break
      }
    }
  
    function storeProperty(obj, prop, type) {
      if(typeof type === 'object') {
        var child = processObject(type)
        Object.defineProperty(obj, prop, {
          get: identity(child),
          set: makeSetter(type),
          enumerable: true,
          configurable: false
        })
      } else {
        if(locations[type]) {
          Object.defineProperty(obj, prop, {
            get: makeGetter(type),
            set: makeSetter(type),
            enumerable: true,
            configurable: false
          })
        } else {
          obj[prop] = defaultValue(uniforms[type].type)
        }
      }
    }
  
    function processObject(obj) {
      var result
      if(Array.isArray(obj)) {
        result = new Array(obj.length)
        for(var i=0; i<obj.length; ++i) {
          storeProperty(result, i, obj[i])
        }
      } else {
        result = {}
        for(var id in obj) {
          storeProperty(result, id, obj[id])
        }
      }
      return result
    }
  
    //Return data
    var coallesced = coallesceUniforms(uniforms, true)
    return {
      get: identity(processObject(coallesced)),
      set: makeSetter(coallesced),
      enumerable: true,
      configurable: true
    }
  }
  
  },{"./reflect":133}],133:[function(require,module,exports){
  'use strict'
  
  module.exports = makeReflectTypes
  
  //Construct type info for reflection.
  //
  // This iterates over the flattened list of uniform type values and smashes them into a JSON object.
  //
  // The leaves of the resulting object are either indices or type strings representing primitive glslify types
  function makeReflectTypes(uniforms, useIndex) {
    var obj = {}
    for(var i=0; i<uniforms.length; ++i) {
      var n = uniforms[i].name
      var parts = n.split(".")
      var o = obj
      for(var j=0; j<parts.length; ++j) {
        var x = parts[j].split("[")
        if(x.length > 1) {
          if(!(x[0] in o)) {
            o[x[0]] = []
          }
          o = o[x[0]]
          for(var k=1; k<x.length; ++k) {
            var y = parseInt(x[k])
            if(k<x.length-1 || j<parts.length-1) {
              if(!(y in o)) {
                if(k < x.length-1) {
                  o[y] = []
                } else {
                  o[y] = {}
                }
              }
              o = o[y]
            } else {
              if(useIndex) {
                o[y] = i
              } else {
                o[y] = uniforms[i].type
              }
            }
          }
        } else if(j < parts.length-1) {
          if(!(x[0] in o)) {
            o[x[0]] = {}
          }
          o = o[x[0]]
        } else {
          if(useIndex) {
            o[x[0]] = i
          } else {
            o[x[0]] = uniforms[i].type
          }
        }
      }
    }
    return obj
  }
  },{}],134:[function(require,module,exports){
  'use strict'
  
  exports.uniforms    = runtimeUniforms
  exports.attributes  = runtimeAttributes
  
  var GL_TO_GLSL_TYPES = {
    'FLOAT':       'float',
    'FLOAT_VEC2':  'vec2',
    'FLOAT_VEC3':  'vec3',
    'FLOAT_VEC4':  'vec4',
    'INT':         'int',
    'INT_VEC2':    'ivec2',
    'INT_VEC3':    'ivec3',
    'INT_VEC4':    'ivec4',
    'BOOL':        'bool',
    'BOOL_VEC2':   'bvec2',
    'BOOL_VEC3':   'bvec3',
    'BOOL_VEC4':   'bvec4',
    'FLOAT_MAT2':  'mat2',
    'FLOAT_MAT3':  'mat3',
    'FLOAT_MAT4':  'mat4',
    'SAMPLER_2D':  'sampler2D',
    'SAMPLER_CUBE':'samplerCube'
  }
  
  var GL_TABLE = null
  
  function getType(gl, type) {
    if(!GL_TABLE) {
      var typeNames = Object.keys(GL_TO_GLSL_TYPES)
      GL_TABLE = {}
      for(var i=0; i<typeNames.length; ++i) {
        var tn = typeNames[i]
        GL_TABLE[gl[tn]] = GL_TO_GLSL_TYPES[tn]
      }
    }
    return GL_TABLE[type]
  }
  
  function runtimeUniforms(gl, program) {
    var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS)
    var result = []
    for(var i=0; i<numUniforms; ++i) {
      var info = gl.getActiveUniform(program, i)
      if(info) {
        var type = getType(gl, info.type)
        if(info.size > 1) {
          for(var j=0; j<info.size; ++j) {
            result.push({
              name: info.name.replace('[0]', '[' + j + ']'),
              type: type
            })
          }
        } else {
          result.push({
            name: info.name,
            type: type
          })
        }
      }
    }
    return result
  }
  
  function runtimeAttributes(gl, program) {
    var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES)
    var result = []
    for(var i=0; i<numAttributes; ++i) {
      var info = gl.getActiveAttrib(program, i)
      if(info) {
        result.push({
          name: info.name,
          type: getType(gl, info.type)
        })
      }
    }
    return result
  }
  
  },{}],135:[function(require,module,exports){
  'use strict'
  
  exports.shader   = getShaderReference
  exports.program  = createProgram
  
  var formatCompilerError = require('gl-format-compiler-error');
  
  var weakMap = typeof WeakMap === 'undefined' ? require('weakmap-shim') : WeakMap
  var CACHE = new weakMap()
  
  var SHADER_COUNTER = 0
  
  function ShaderReference(id, src, type, shader, programs, count, cache) {
    this.id       = id
    this.src      = src
    this.type     = type
    this.shader   = shader
    this.count    = count
    this.programs = []
    this.cache    = cache
  }
  
  ShaderReference.prototype.dispose = function() {
    if(--this.count === 0) {
      var cache    = this.cache
      var gl       = cache.gl
  
      //Remove program references
      var programs = this.programs
      for(var i=0, n=programs.length; i<n; ++i) {
        var p = cache.programs[programs[i]]
        if(p) {
          delete cache.programs[i]
          gl.deleteProgram(p)
        }
      }
  
      //Remove shader reference
      gl.deleteShader(this.shader)
      delete cache.shaders[(this.type === gl.FRAGMENT_SHADER)|0][this.src]
    }
  }
  
  function ContextCache(gl) {
    this.gl       = gl
    this.shaders  = [{}, {}]
    this.programs = {}
  }
  
  var proto = ContextCache.prototype
  
  function compileShader(gl, type, src) {
    var shader = gl.createShader(type)
    gl.shaderSource(shader, src)
    gl.compileShader(shader)
    if(!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      var errLog = gl.getShaderInfoLog(shader)
      try {
          var fmt = formatCompilerError(errLog, src, type);
      } catch (e){
          console.warn('Failed to format compiler error: ' + e);
          throw new Error('gl-shader: Error compiling shader:\n' + errLog)
      }
      console.warn('gl-shader: ' + fmt.long);
      throw new Error('gl-shader: ' + fmt.short)
    }
    return shader
  }
  
  proto.getShaderReference = function(type, src) {
    var gl      = this.gl
    var shaders = this.shaders[(type === gl.FRAGMENT_SHADER)|0]
    var shader  = shaders[src]
    if(!shader || !gl.isShader(shader.shader)) {
      var shaderObj = compileShader(gl, type, src)
      shader = shaders[src] = new ShaderReference(
        SHADER_COUNTER++,
        src,
        type,
        shaderObj,
        [],
        1,
        this)
    } else {
      shader.count += 1
    }
    return shader
  }
  
  function linkProgram(gl, vshader, fshader, attribs, locations) {
    var program = gl.createProgram()
    gl.attachShader(program, vshader)
    gl.attachShader(program, fshader)
    for(var i=0; i<attribs.length; ++i) {
      gl.bindAttribLocation(program, locations[i], attribs[i])
    }
    gl.linkProgram(program)
    if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {
      var errLog = gl.getProgramInfoLog(program)
      console.error('gl-shader: Error linking program:', errLog)
      throw new Error('gl-shader: Error linking program:' + errLog)
    }
    return program
  }
  
  proto.getProgram = function(vref, fref, attribs, locations) {
    var token = [vref.id, fref.id, attribs.join(':'), locations.join(':')].join('@')
    var prog  = this.programs[token]
    if(!prog || !this.gl.isProgram(prog)) {
      this.programs[token] = prog = linkProgram(
        this.gl,
        vref.shader,
        fref.shader,
        attribs,
        locations)
      vref.programs.push(token)
      fref.programs.push(token)
    }
    return prog
  }
  
  function getCache(gl) {
    var ctxCache = CACHE.get(gl)
    if(!ctxCache) {
      ctxCache = new ContextCache(gl)
      CACHE.set(gl, ctxCache)
    }
    return ctxCache
  }
  
  function getShaderReference(gl, type, src) {
    return getCache(gl).getShaderReference(type, src)
  }
  
  function createProgram(gl, vref, fref, attribs, locations) {
    return getCache(gl).getProgram(vref, fref, attribs, locations)
  }
  
  },{"gl-format-compiler-error":65,"weakmap-shim":273}],136:[function(require,module,exports){
  module.exports = glToType
  function glToType (flag) {
    switch (flag) {
      case 5126: return 'float32'   // gl.FLOAT
      case 5125: return 'uint32'    // gl.UNSIGNED_INT
      case 5124: return 'int32'     // gl.INT
      case 5123: return 'uint16'    // gl.UNSIGNED_SHORT
      case 32819: return 'uint16'   // gl.UNSIGNED_SHORT_4_4_4_4
      case 32820: return 'uint16'   // gl.UNSIGNED_SHORT_5_5_5_1
      case 33635: return 'uint16'   // gl.UNSIGNED_SHORT_5_6_5
      case 5122: return 'int16'     // gl.SHORT
      case 5121: return 'uint8'     // gl.UNSIGNED_BYTE
      case 5120: return 'int8'      // gl.BYTE
      default: return null
    }
  }
  
  },{}],137:[function(require,module,exports){
  "use strict"
  
  function doBind(gl, elements, attributes) {
    if(elements) {
      elements.bind()
    } else {
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null)
    }
    var nattribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS)|0
    if(attributes) {
      if(attributes.length > nattribs) {
        throw new Error("gl-vao: Too many vertex attributes")
      }
      for(var i=0; i<attributes.length; ++i) {
        var attrib = attributes[i]
        if(attrib.buffer) {
          var buffer = attrib.buffer
          var size = attrib.size || 4
          var type = attrib.type || gl.FLOAT
          var normalized = !!attrib.normalized
          var stride = attrib.stride || 0
          var offset = attrib.offset || 0
          buffer.bind()
          gl.enableVertexAttribArray(i)
          gl.vertexAttribPointer(i, size, type, normalized, stride, offset)
        } else {
          if(typeof attrib === "number") {
            gl.vertexAttrib1f(i, attrib)
          } else if(attrib.length === 1) {
            gl.vertexAttrib1f(i, attrib[0])
          } else if(attrib.length === 2) {
            gl.vertexAttrib2f(i, attrib[0], attrib[1])
          } else if(attrib.length === 3) {
            gl.vertexAttrib3f(i, attrib[0], attrib[1], attrib[2])
          } else if(attrib.length === 4) {
            gl.vertexAttrib4f(i, attrib[0], attrib[1], attrib[2], attrib[3])
          } else {
            throw new Error("gl-vao: Invalid vertex attribute")
          }
          gl.disableVertexAttribArray(i)
        }
      }
      for(; i<nattribs; ++i) {
        gl.disableVertexAttribArray(i)
      }
    } else {
      gl.bindBuffer(gl.ARRAY_BUFFER, null)
      for(var i=0; i<nattribs; ++i) {
        gl.disableVertexAttribArray(i)
      }
    }
  }
  
  module.exports = doBind
  },{}],138:[function(require,module,exports){
  "use strict"
  
  var bindAttribs = require("./do-bind.js")
  
  function VAOEmulated(gl) {
    this.gl = gl
    this._elements = null
    this._attributes = null
    this._elementsType = gl.UNSIGNED_SHORT
  }
  
  VAOEmulated.prototype.bind = function() {
    bindAttribs(this.gl, this._elements, this._attributes)
  }
  
  VAOEmulated.prototype.update = function(attributes, elements, elementsType) {
    this._elements = elements
    this._attributes = attributes
    this._elementsType = elementsType || this.gl.UNSIGNED_SHORT
  }
  
  VAOEmulated.prototype.dispose = function() { }
  VAOEmulated.prototype.unbind = function() { }
  
  VAOEmulated.prototype.draw = function(mode, count, offset) {
    offset = offset || 0
    var gl = this.gl
    if(this._elements) {
      gl.drawElements(mode, count, this._elementsType, offset)
    } else {
      gl.drawArrays(mode, offset, count)
    }
  }
  
  function createVAOEmulated(gl) {
    return new VAOEmulated(gl)
  }
  
  module.exports = createVAOEmulated
  },{"./do-bind.js":137}],139:[function(require,module,exports){
  "use strict"
  
  var bindAttribs = require("./do-bind.js")
  
  function VertexAttribute(location, dimension, a, b, c, d) {
    this.location = location
    this.dimension = dimension
    this.a = a
    this.b = b
    this.c = c
    this.d = d
  }
  
  VertexAttribute.prototype.bind = function(gl) {
    switch(this.dimension) {
      case 1:
        gl.vertexAttrib1f(this.location, this.a)
      break
      case 2:
        gl.vertexAttrib2f(this.location, this.a, this.b)
      break
      case 3:
        gl.vertexAttrib3f(this.location, this.a, this.b, this.c)
      break
      case 4:
        gl.vertexAttrib4f(this.location, this.a, this.b, this.c, this.d)
      break
    }
  }
  
  function VAONative(gl, ext, handle) {
    this.gl = gl
    this._ext = ext
    this.handle = handle
    this._attribs = []
    this._useElements = false
    this._elementsType = gl.UNSIGNED_SHORT
  }
  
  VAONative.prototype.bind = function() {
    this._ext.bindVertexArrayOES(this.handle)
    for(var i=0; i<this._attribs.length; ++i) {
      this._attribs[i].bind(this.gl)
    }
  }
  
  VAONative.prototype.unbind = function() {
    this._ext.bindVertexArrayOES(null)
  }
  
  VAONative.prototype.dispose = function() {
    this._ext.deleteVertexArrayOES(this.handle)
  }
  
  VAONative.prototype.update = function(attributes, elements, elementsType) {
    this.bind()
    bindAttribs(this.gl, elements, attributes)
    this.unbind()
    this._attribs.length = 0
    if(attributes)
    for(var i=0; i<attributes.length; ++i) {
      var a = attributes[i]
      if(typeof a === "number") {
        this._attribs.push(new VertexAttribute(i, 1, a))
      } else if(Array.isArray(a)) {
        this._attribs.push(new VertexAttribute(i, a.length, a[0], a[1], a[2], a[3]))
      }
    }
    this._useElements = !!elements
    this._elementsType = elementsType || this.gl.UNSIGNED_SHORT
  }
  
  VAONative.prototype.draw = function(mode, count, offset) {
    offset = offset || 0
    var gl = this.gl
    if(this._useElements) {
      gl.drawElements(mode, count, this._elementsType, offset)
    } else {
      gl.drawArrays(mode, offset, count)
    }
  }
  
  function createVAONative(gl, ext) {
    return new VAONative(gl, ext, ext.createVertexArrayOES())
  }
  
  module.exports = createVAONative
  },{"./do-bind.js":137}],140:[function(require,module,exports){
  "use strict"
  
  var createVAONative = require("./lib/vao-native.js")
  var createVAOEmulated = require("./lib/vao-emulated.js")
  
  function createVAO(gl, attributes, elements, elementsType) {
    var ext = gl.getExtension('OES_vertex_array_object')
    var vao
    if(ext) {
      vao = createVAONative(gl, ext)
    } else {
      vao = createVAOEmulated(gl)
    }
    vao.update(attributes, elements, elementsType)
    return vao
  }
  
  module.exports = createVAO
  
  },{"./lib/vao-emulated.js":138,"./lib/vao-native.js":139}],141:[function(require,module,exports){
  module.exports = add;
  
  /**
   * Adds two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  function add(out, a, b) {
      out[0] = a[0] + b[0]
      out[1] = a[1] + b[1]
      out[2] = a[2] + b[2]
      return out
  }
  },{}],142:[function(require,module,exports){
  module.exports = angle
  
  var fromValues = require('./fromValues')
  var normalize = require('./normalize')
  var dot = require('./dot')
  
  /**
   * Get the angle between two 3D vectors
   * @param {vec3} a The first operand
   * @param {vec3} b The second operand
   * @returns {Number} The angle in radians
   */
  function angle(a, b) {
      var tempA = fromValues(a[0], a[1], a[2])
      var tempB = fromValues(b[0], b[1], b[2])
   
      normalize(tempA, tempA)
      normalize(tempB, tempB)
   
      var cosine = dot(tempA, tempB)
  
      if(cosine > 1.0){
          return 0
      } else {
          return Math.acos(cosine)
      }     
  }
  
  },{"./dot":149,"./fromValues":151,"./normalize":160}],143:[function(require,module,exports){
  module.exports = clone;
  
  /**
   * Creates a new vec3 initialized with values from an existing vector
   *
   * @param {vec3} a vector to clone
   * @returns {vec3} a new 3D vector
   */
  function clone(a) {
      var out = new Float32Array(3)
      out[0] = a[0]
      out[1] = a[1]
      out[2] = a[2]
      return out
  }
  },{}],144:[function(require,module,exports){
  module.exports = copy;
  
  /**
   * Copy the values from one vec3 to another
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the source vector
   * @returns {vec3} out
   */
  function copy(out, a) {
      out[0] = a[0]
      out[1] = a[1]
      out[2] = a[2]
      return out
  }
  },{}],145:[function(require,module,exports){
  module.exports = create;
  
  /**
   * Creates a new, empty vec3
   *
   * @returns {vec3} a new 3D vector
   */
  function create() {
      var out = new Float32Array(3)
      out[0] = 0
      out[1] = 0
      out[2] = 0
      return out
  }
  },{}],146:[function(require,module,exports){
  module.exports = cross;
  
  /**
   * Computes the cross product of two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  function cross(out, a, b) {
      var ax = a[0], ay = a[1], az = a[2],
          bx = b[0], by = b[1], bz = b[2]
  
      out[0] = ay * bz - az * by
      out[1] = az * bx - ax * bz
      out[2] = ax * by - ay * bx
      return out
  }
  },{}],147:[function(require,module,exports){
  module.exports = distance;
  
  /**
   * Calculates the euclidian distance between two vec3's
   *
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {Number} distance between a and b
   */
  function distance(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1],
          z = b[2] - a[2]
      return Math.sqrt(x*x + y*y + z*z)
  }
  },{}],148:[function(require,module,exports){
  module.exports = divide;
  
  /**
   * Divides two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  function divide(out, a, b) {
      out[0] = a[0] / b[0]
      out[1] = a[1] / b[1]
      out[2] = a[2] / b[2]
      return out
  }
  },{}],149:[function(require,module,exports){
  module.exports = dot;
  
  /**
   * Calculates the dot product of two vec3's
   *
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {Number} dot product of a and b
   */
  function dot(a, b) {
      return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
  }
  },{}],150:[function(require,module,exports){
  module.exports = forEach;
  
  var vec = require('./create')()
  
  /**
   * Perform some operation over an array of vec3s.
   *
   * @param {Array} a the array of vectors to iterate over
   * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
   * @param {Number} offset Number of elements to skip at the beginning of the array
   * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
   * @param {Function} fn Function to call for each vector in the array
   * @param {Object} [arg] additional argument to pass to fn
   * @returns {Array} a
   * @function
   */
  function forEach(a, stride, offset, count, fn, arg) {
          var i, l
          if(!stride) {
              stride = 3
          }
  
          if(!offset) {
              offset = 0
          }
          
          if(count) {
              l = Math.min((count * stride) + offset, a.length)
          } else {
              l = a.length
          }
  
          for(i = offset; i < l; i += stride) {
              vec[0] = a[i] 
              vec[1] = a[i+1] 
              vec[2] = a[i+2]
              fn(vec, vec, arg)
              a[i] = vec[0] 
              a[i+1] = vec[1] 
              a[i+2] = vec[2]
          }
          
          return a
  }
  },{"./create":145}],151:[function(require,module,exports){
  module.exports = fromValues;
  
  /**
   * Creates a new vec3 initialized with the given values
   *
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @returns {vec3} a new 3D vector
   */
  function fromValues(x, y, z) {
      var out = new Float32Array(3)
      out[0] = x
      out[1] = y
      out[2] = z
      return out
  }
  },{}],152:[function(require,module,exports){
  module.exports = {
    create: require('./create')
    , clone: require('./clone')
    , angle: require('./angle')
    , fromValues: require('./fromValues')
    , copy: require('./copy')
    , set: require('./set')
    , add: require('./add')
    , subtract: require('./subtract')
    , multiply: require('./multiply')
    , divide: require('./divide')
    , min: require('./min')
    , max: require('./max')
    , scale: require('./scale')
    , scaleAndAdd: require('./scaleAndAdd')
    , distance: require('./distance')
    , squaredDistance: require('./squaredDistance')
    , length: require('./length')
    , squaredLength: require('./squaredLength')
    , negate: require('./negate')
    , inverse: require('./inverse')
    , normalize: require('./normalize')
    , dot: require('./dot')
    , cross: require('./cross')
    , lerp: require('./lerp')
    , random: require('./random')
    , transformMat4: require('./transformMat4')
    , transformMat3: require('./transformMat3')
    , transformQuat: require('./transformQuat')
    , rotateX: require('./rotateX')
    , rotateY: require('./rotateY')
    , rotateZ: require('./rotateZ')
    , forEach: require('./forEach')
  }
  },{"./add":141,"./angle":142,"./clone":143,"./copy":144,"./create":145,"./cross":146,"./distance":147,"./divide":148,"./dot":149,"./forEach":150,"./fromValues":151,"./inverse":153,"./length":154,"./lerp":155,"./max":156,"./min":157,"./multiply":158,"./negate":159,"./normalize":160,"./random":161,"./rotateX":162,"./rotateY":163,"./rotateZ":164,"./scale":165,"./scaleAndAdd":166,"./set":167,"./squaredDistance":168,"./squaredLength":169,"./subtract":170,"./transformMat3":171,"./transformMat4":172,"./transformQuat":173}],153:[function(require,module,exports){
  module.exports = inverse;
  
  /**
   * Returns the inverse of the components of a vec3
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a vector to invert
   * @returns {vec3} out
   */
  function inverse(out, a) {
    out[0] = 1.0 / a[0]
    out[1] = 1.0 / a[1]
    out[2] = 1.0 / a[2]
    return out
  }
  },{}],154:[function(require,module,exports){
  module.exports = length;
  
  /**
   * Calculates the length of a vec3
   *
   * @param {vec3} a vector to calculate length of
   * @returns {Number} length of a
   */
  function length(a) {
      var x = a[0],
          y = a[1],
          z = a[2]
      return Math.sqrt(x*x + y*y + z*z)
  }
  },{}],155:[function(require,module,exports){
  module.exports = lerp;
  
  /**
   * Performs a linear interpolation between two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {vec3} out
   */
  function lerp(out, a, b, t) {
      var ax = a[0],
          ay = a[1],
          az = a[2]
      out[0] = ax + t * (b[0] - ax)
      out[1] = ay + t * (b[1] - ay)
      out[2] = az + t * (b[2] - az)
      return out
  }
  },{}],156:[function(require,module,exports){
  module.exports = max;
  
  /**
   * Returns the maximum of two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  function max(out, a, b) {
      out[0] = Math.max(a[0], b[0])
      out[1] = Math.max(a[1], b[1])
      out[2] = Math.max(a[2], b[2])
      return out
  }
  },{}],157:[function(require,module,exports){
  module.exports = min;
  
  /**
   * Returns the minimum of two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  function min(out, a, b) {
      out[0] = Math.min(a[0], b[0])
      out[1] = Math.min(a[1], b[1])
      out[2] = Math.min(a[2], b[2])
      return out
  }
  },{}],158:[function(require,module,exports){
  module.exports = multiply;
  
  /**
   * Multiplies two vec3's
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  function multiply(out, a, b) {
      out[0] = a[0] * b[0]
      out[1] = a[1] * b[1]
      out[2] = a[2] * b[2]
      return out
  }
  },{}],159:[function(require,module,exports){
  module.exports = negate;
  
  /**
   * Negates the components of a vec3
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a vector to negate
   * @returns {vec3} out
   */
  function negate(out, a) {
      out[0] = -a[0]
      out[1] = -a[1]
      out[2] = -a[2]
      return out
  }
  },{}],160:[function(require,module,exports){
  module.exports = normalize;
  
  /**
   * Normalize a vec3
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a vector to normalize
   * @returns {vec3} out
   */
  function normalize(out, a) {
      var x = a[0],
          y = a[1],
          z = a[2]
      var len = x*x + y*y + z*z
      if (len > 0) {
          //TODO: evaluate use of glm_invsqrt here?
          len = 1 / Math.sqrt(len)
          out[0] = a[0] * len
          out[1] = a[1] * len
          out[2] = a[2] * len
      }
      return out
  }
  },{}],161:[function(require,module,exports){
  module.exports = random;
  
  /**
   * Generates a random vector with the given scale
   *
   * @param {vec3} out the receiving vector
   * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
   * @returns {vec3} out
   */
  function random(out, scale) {
      scale = scale || 1.0
  
      var r = Math.random() * 2.0 * Math.PI
      var z = (Math.random() * 2.0) - 1.0
      var zScale = Math.sqrt(1.0-z*z) * scale
  
      out[0] = Math.cos(r) * zScale
      out[1] = Math.sin(r) * zScale
      out[2] = z * scale
      return out
  }
  },{}],162:[function(require,module,exports){
  module.exports = rotateX;
  
  /**
   * Rotate a 3D vector around the x-axis
   * @param {vec3} out The receiving vec3
   * @param {vec3} a The vec3 point to rotate
   * @param {vec3} b The origin of the rotation
   * @param {Number} c The angle of rotation
   * @returns {vec3} out
   */
  function rotateX(out, a, b, c){
      var p = [], r=[]
      //Translate point to the origin
      p[0] = a[0] - b[0]
      p[1] = a[1] - b[1]
      p[2] = a[2] - b[2]
  
      //perform rotation
      r[0] = p[0]
      r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c)
      r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c)
  
      //translate to correct position
      out[0] = r[0] + b[0]
      out[1] = r[1] + b[1]
      out[2] = r[2] + b[2]
  
      return out
  }
  },{}],163:[function(require,module,exports){
  module.exports = rotateY;
  
  /**
   * Rotate a 3D vector around the y-axis
   * @param {vec3} out The receiving vec3
   * @param {vec3} a The vec3 point to rotate
   * @param {vec3} b The origin of the rotation
   * @param {Number} c The angle of rotation
   * @returns {vec3} out
   */
  function rotateY(out, a, b, c){
      var p = [], r=[]
      //Translate point to the origin
      p[0] = a[0] - b[0]
      p[1] = a[1] - b[1]
      p[2] = a[2] - b[2]
    
      //perform rotation
      r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c)
      r[1] = p[1]
      r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c)
    
      //translate to correct position
      out[0] = r[0] + b[0]
      out[1] = r[1] + b[1]
      out[2] = r[2] + b[2]
    
      return out
  }
  },{}],164:[function(require,module,exports){
  module.exports = rotateZ;
  
  /**
   * Rotate a 3D vector around the z-axis
   * @param {vec3} out The receiving vec3
   * @param {vec3} a The vec3 point to rotate
   * @param {vec3} b The origin of the rotation
   * @param {Number} c The angle of rotation
   * @returns {vec3} out
   */
  function rotateZ(out, a, b, c){
      var p = [], r=[]
      //Translate point to the origin
      p[0] = a[0] - b[0]
      p[1] = a[1] - b[1]
      p[2] = a[2] - b[2]
    
      //perform rotation
      r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c)
      r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c)
      r[2] = p[2]
    
      //translate to correct position
      out[0] = r[0] + b[0]
      out[1] = r[1] + b[1]
      out[2] = r[2] + b[2]
    
      return out
  }
  },{}],165:[function(require,module,exports){
  module.exports = scale;
  
  /**
   * Scales a vec3 by a scalar number
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the vector to scale
   * @param {Number} b amount to scale the vector by
   * @returns {vec3} out
   */
  function scale(out, a, b) {
      out[0] = a[0] * b
      out[1] = a[1] * b
      out[2] = a[2] * b
      return out
  }
  },{}],166:[function(require,module,exports){
  module.exports = scaleAndAdd;
  
  /**
   * Adds two vec3's after scaling the second operand by a scalar value
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @param {Number} scale the amount to scale b by before adding
   * @returns {vec3} out
   */
  function scaleAndAdd(out, a, b, scale) {
      out[0] = a[0] + (b[0] * scale)
      out[1] = a[1] + (b[1] * scale)
      out[2] = a[2] + (b[2] * scale)
      return out
  }
  },{}],167:[function(require,module,exports){
  module.exports = set;
  
  /**
   * Set the components of a vec3 to the given values
   *
   * @param {vec3} out the receiving vector
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @returns {vec3} out
   */
  function set(out, x, y, z) {
      out[0] = x
      out[1] = y
      out[2] = z
      return out
  }
  },{}],168:[function(require,module,exports){
  module.exports = squaredDistance;
  
  /**
   * Calculates the squared euclidian distance between two vec3's
   *
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {Number} squared distance between a and b
   */
  function squaredDistance(a, b) {
      var x = b[0] - a[0],
          y = b[1] - a[1],
          z = b[2] - a[2]
      return x*x + y*y + z*z
  }
  },{}],169:[function(require,module,exports){
  module.exports = squaredLength;
  
  /**
   * Calculates the squared length of a vec3
   *
   * @param {vec3} a vector to calculate squared length of
   * @returns {Number} squared length of a
   */
  function squaredLength(a) {
      var x = a[0],
          y = a[1],
          z = a[2]
      return x*x + y*y + z*z
  }
  },{}],170:[function(require,module,exports){
  module.exports = subtract;
  
  /**
   * Subtracts vector b from vector a
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the first operand
   * @param {vec3} b the second operand
   * @returns {vec3} out
   */
  function subtract(out, a, b) {
      out[0] = a[0] - b[0]
      out[1] = a[1] - b[1]
      out[2] = a[2] - b[2]
      return out
  }
  },{}],171:[function(require,module,exports){
  module.exports = transformMat3;
  
  /**
   * Transforms the vec3 with a mat3.
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the vector to transform
   * @param {mat4} m the 3x3 matrix to transform with
   * @returns {vec3} out
   */
  function transformMat3(out, a, m) {
      var x = a[0], y = a[1], z = a[2]
      out[0] = x * m[0] + y * m[3] + z * m[6]
      out[1] = x * m[1] + y * m[4] + z * m[7]
      out[2] = x * m[2] + y * m[5] + z * m[8]
      return out
  }
  },{}],172:[function(require,module,exports){
  module.exports = transformMat4;
  
  /**
   * Transforms the vec3 with a mat4.
   * 4th vector component is implicitly '1'
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the vector to transform
   * @param {mat4} m matrix to transform with
   * @returns {vec3} out
   */
  function transformMat4(out, a, m) {
      var x = a[0], y = a[1], z = a[2],
          w = m[3] * x + m[7] * y + m[11] * z + m[15]
      w = w || 1.0
      out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w
      out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w
      out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w
      return out
  }
  },{}],173:[function(require,module,exports){
  module.exports = transformQuat;
  
  /**
   * Transforms the vec3 with a quat
   *
   * @param {vec3} out the receiving vector
   * @param {vec3} a the vector to transform
   * @param {quat} q quaternion to transform with
   * @returns {vec3} out
   */
  function transformQuat(out, a, q) {
      // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
  
      var x = a[0], y = a[1], z = a[2],
          qx = q[0], qy = q[1], qz = q[2], qw = q[3],
  
          // calculate quat * vec
          ix = qw * x + qy * z - qz * y,
          iy = qw * y + qz * x - qx * z,
          iz = qw * z + qx * y - qy * x,
          iw = -qx * x - qy * y - qz * z
  
      // calculate result * inverse quat
      out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy
      out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz
      out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx
      return out
  }
  },{}],174:[function(require,module,exports){
  module.exports = add
  
  /**
   * Adds two vec4's
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {vec4} out
   */
  function add (out, a, b) {
    out[0] = a[0] + b[0]
    out[1] = a[1] + b[1]
    out[2] = a[2] + b[2]
    out[3] = a[3] + b[3]
    return out
  }
  
  },{}],175:[function(require,module,exports){
  module.exports = clone
  
  /**
   * Creates a new vec4 initialized with values from an existing vector
   *
   * @param {vec4} a vector to clone
   * @returns {vec4} a new 4D vector
   */
  function clone (a) {
    var out = new Float32Array(4)
    out[0] = a[0]
    out[1] = a[1]
    out[2] = a[2]
    out[3] = a[3]
    return out
  }
  
  },{}],176:[function(require,module,exports){
  module.exports = copy
  
  /**
   * Copy the values from one vec4 to another
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the source vector
   * @returns {vec4} out
   */
  function copy (out, a) {
    out[0] = a[0]
    out[1] = a[1]
    out[2] = a[2]
    out[3] = a[3]
    return out
  }
  
  },{}],177:[function(require,module,exports){
  module.exports = dot
  
  /**
   * Calculates the dot product of two vec4's
   *
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @returns {Number} dot product of a and b
   */
  function dot (a, b) {
    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]
  }
  
  },{}],178:[function(require,module,exports){
  module.exports = fromValues
  
  /**
   * Creates a new vec4 initialized with the given values
   *
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @param {Number} w W component
   * @returns {vec4} a new 4D vector
   */
  function fromValues (x, y, z, w) {
    var out = new Float32Array(4)
    out[0] = x
    out[1] = y
    out[2] = z
    out[3] = w
    return out
  }
  
  },{}],179:[function(require,module,exports){
  module.exports = length
  
  /**
   * Calculates the length of a vec4
   *
   * @param {vec4} a vector to calculate length of
   * @returns {Number} length of a
   */
  function length (a) {
    var x = a[0],
      y = a[1],
      z = a[2],
      w = a[3]
    return Math.sqrt(x * x + y * y + z * z + w * w)
  }
  
  },{}],180:[function(require,module,exports){
  module.exports = lerp
  
  /**
   * Performs a linear interpolation between two vec4's
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the first operand
   * @param {vec4} b the second operand
   * @param {Number} t interpolation amount between the two inputs
   * @returns {vec4} out
   */
  function lerp (out, a, b, t) {
    var ax = a[0],
      ay = a[1],
      az = a[2],
      aw = a[3]
    out[0] = ax + t * (b[0] - ax)
    out[1] = ay + t * (b[1] - ay)
    out[2] = az + t * (b[2] - az)
    out[3] = aw + t * (b[3] - aw)
    return out
  }
  
  },{}],181:[function(require,module,exports){
  module.exports = normalize
  
  /**
   * Normalize a vec4
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a vector to normalize
   * @returns {vec4} out
   */
  function normalize (out, a) {
    var x = a[0],
      y = a[1],
      z = a[2],
      w = a[3]
    var len = x * x + y * y + z * z + w * w
    if (len > 0) {
      len = 1 / Math.sqrt(len)
      out[0] = x * len
      out[1] = y * len
      out[2] = z * len
      out[3] = w * len
    }
    return out
  }
  
  },{}],182:[function(require,module,exports){
  module.exports = scale
  
  /**
   * Scales a vec4 by a scalar number
   *
   * @param {vec4} out the receiving vector
   * @param {vec4} a the vector to scale
   * @param {Number} b amount to scale the vector by
   * @returns {vec4} out
   */
  function scale (out, a, b) {
    out[0] = a[0] * b
    out[1] = a[1] * b
    out[2] = a[2] * b
    out[3] = a[3] * b
    return out
  }
  
  },{}],183:[function(require,module,exports){
  module.exports = set
  
  /**
   * Set the components of a vec4 to the given values
   *
   * @param {vec4} out the receiving vector
   * @param {Number} x X component
   * @param {Number} y Y component
   * @param {Number} z Z component
   * @param {Number} w W component
   * @returns {vec4} out
   */
  function set (out, x, y, z, w) {
    out[0] = x
    out[1] = y
    out[2] = z
    out[3] = w
    return out
  }
  
  },{}],184:[function(require,module,exports){
  module.exports = squaredLength
  
  /**
   * Calculates the squared length of a vec4
   *
   * @param {vec4} a vector to calculate squared length of
   * @returns {Number} squared length of a
   */
  function squaredLength (a) {
    var x = a[0],
      y = a[1],
      z = a[2],
      w = a[3]
    return x * x + y * y + z * z + w * w
  }
  
  },{}],185:[function(require,module,exports){
  (function (global){
  if (typeof window !== "undefined") {
      module.exports = window;
  } else if (typeof global !== "undefined") {
      module.exports = global;
  } else if (typeof self !== "undefined"){
      module.exports = self;
  } else {
      module.exports = {};
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],186:[function(require,module,exports){
  var tokenize = require('glsl-tokenizer')
  var atob     = require('atob-lite')
  
  module.exports = getName
  
  function getName(src) {
    var tokens = Array.isArray(src)
      ? src
      : tokenize(src)
  
    for (var i = 0; i < tokens.length; i++) {
      var token = tokens[i]
      if (token.type !== 'preprocessor') continue
      var match = token.data.match(/\#define\s+SHADER_NAME(_B64)?\s+(.+)$/)
      if (!match) continue
      if (!match[2]) continue
  
      var b64  = match[1]
      var name = match[2]
  
      return (b64 ? atob(name) : name).trim()
    }
  }
  
  },{"atob-lite":8,"glsl-tokenizer":191}],187:[function(require,module,exports){
  module.exports = tokenize
  
  var literals = require('./lib/literals')
    , operators = require('./lib/operators')
    , builtins = require('./lib/builtins')
  
  var NORMAL = 999          // <-- never emitted
    , TOKEN = 9999          // <-- never emitted
    , BLOCK_COMMENT = 0
    , LINE_COMMENT = 1
    , PREPROCESSOR = 2
    , OPERATOR = 3
    , INTEGER = 4
    , FLOAT = 5
    , IDENT = 6
    , BUILTIN = 7
    , KEYWORD = 8
    , WHITESPACE = 9
    , EOF = 10
    , HEX = 11
  
  var map = [
      'block-comment'
    , 'line-comment'
    , 'preprocessor'
    , 'operator'
    , 'integer'
    , 'float'
    , 'ident'
    , 'builtin'
    , 'keyword'
    , 'whitespace'
    , 'eof'
    , 'integer'
  ]
  
  function tokenize() {
    var i = 0
      , total = 0
      , mode = NORMAL
      , c
      , last
      , content = []
      , tokens = []
      , token_idx = 0
      , token_offs = 0
      , line = 1
      , col = 0
      , start = 0
      , isnum = false
      , isoperator = false
      , input = ''
      , len
  
    return function(data) {
      tokens = []
      if (data !== null) return write(data)
      return end()
    }
  
    function token(data) {
      if (data.length) {
        tokens.push({
          type: map[mode]
        , data: data
        , position: start
        , line: line
        , column: col
        })
      }
    }
  
    function write(chunk) {
      i = 0
      input += chunk
      len = input.length
  
      var last
  
      while(c = input[i], i < len) {
        last = i
  
        switch(mode) {
          case BLOCK_COMMENT: i = block_comment(); break
          case LINE_COMMENT: i = line_comment(); break
          case PREPROCESSOR: i = preprocessor(); break
          case OPERATOR: i = operator(); break
          case INTEGER: i = integer(); break
          case HEX: i = hex(); break
          case FLOAT: i = decimal(); break
          case TOKEN: i = readtoken(); break
          case WHITESPACE: i = whitespace(); break
          case NORMAL: i = normal(); break
        }
  
        if(last !== i) {
          switch(input[last]) {
            case '\n': col = 0; ++line; break
            default: ++col; break
          }
        }
      }
  
      total += i
      input = input.slice(i)
      return tokens
    }
  
    function end(chunk) {
      if(content.length) {
        token(content.join(''))
      }
  
      mode = EOF
      token('(eof)')
      return tokens
    }
  
    function normal() {
      content = content.length ? [] : content
  
      if(last === '/' && c === '*') {
        start = total + i - 1
        mode = BLOCK_COMMENT
        last = c
        return i + 1
      }
  
      if(last === '/' && c === '/') {
        start = total + i - 1
        mode = LINE_COMMENT
        last = c
        return i + 1
      }
  
      if(c === '#') {
        mode = PREPROCESSOR
        start = total + i
        return i
      }
  
      if(/\s/.test(c)) {
        mode = WHITESPACE
        start = total + i
        return i
      }
  
      isnum = /\d/.test(c)
      isoperator = /[^\w_]/.test(c)
  
      start = total + i
      mode = isnum ? INTEGER : isoperator ? OPERATOR : TOKEN
      return i
    }
  
    function whitespace() {
      if(/[^\s]/g.test(c)) {
        token(content.join(''))
        mode = NORMAL
        return i
      }
      content.push(c)
      last = c
      return i + 1
    }
  
    function preprocessor() {
      if(c === '\n' && last !== '\\') {
        token(content.join(''))
        mode = NORMAL
        return i
      }
      content.push(c)
      last = c
      return i + 1
    }
  
    function line_comment() {
      return preprocessor()
    }
  
    function block_comment() {
      if(c === '/' && last === '*') {
        content.push(c)
        token(content.join(''))
        mode = NORMAL
        return i + 1
      }
  
      content.push(c)
      last = c
      return i + 1
    }
  
    function operator() {
      if(last === '.' && /\d/.test(c)) {
        mode = FLOAT
        return i
      }
  
      if(last === '/' && c === '*') {
        mode = BLOCK_COMMENT
        return i
      }
  
      if(last === '/' && c === '/') {
        mode = LINE_COMMENT
        return i
      }
  
      if(c === '.' && content.length) {
        while(determine_operator(content));
  
        mode = FLOAT
        return i
      }
  
      if(c === ';' || c === ')' || c === '(') {
        if(content.length) while(determine_operator(content));
        token(c)
        mode = NORMAL
        return i + 1
      }
  
      var is_composite_operator = content.length === 2 && c !== '='
      if(/[\w_\d\s]/.test(c) || is_composite_operator) {
        while(determine_operator(content));
        mode = NORMAL
        return i
      }
  
      content.push(c)
      last = c
      return i + 1
    }
  
    function determine_operator(buf) {
      var j = 0
        , idx
        , res
  
      do {
        idx = operators.indexOf(buf.slice(0, buf.length + j).join(''))
        res = operators[idx]
  
        if(idx === -1) {
          if(j-- + buf.length > 0) continue
          res = buf.slice(0, 1).join('')
        }
  
        token(res)
  
        start += res.length
        content = content.slice(res.length)
        return content.length
      } while(1)
    }
  
    function hex() {
      if(/[^a-fA-F0-9]/.test(c)) {
        token(content.join(''))
        mode = NORMAL
        return i
      }
  
      content.push(c)
      last = c
      return i + 1
    }
  
    function integer() {
      if(c === '.') {
        content.push(c)
        mode = FLOAT
        last = c
        return i + 1
      }
  
      if(/[eE]/.test(c)) {
        content.push(c)
        mode = FLOAT
        last = c
        return i + 1
      }
  
      if(c === 'x' && content.length === 1 && content[0] === '0') {
        mode = HEX
        content.push(c)
        last = c
        return i + 1
      }
  
      if(/[^\d]/.test(c)) {
        token(content.join(''))
        mode = NORMAL
        return i
      }
  
      content.push(c)
      last = c
      return i + 1
    }
  
    function decimal() {
      if(c === 'f') {
        content.push(c)
        last = c
        i += 1
      }
  
      if(/[eE]/.test(c)) {
        content.push(c)
        last = c
        return i + 1
      }
  
      if(/[^\d]/.test(c)) {
        token(content.join(''))
        mode = NORMAL
        return i
      }
      content.push(c)
      last = c
      return i + 1
    }
  
    function readtoken() {
      if(/[^\d\w_]/.test(c)) {
        var contentstr = content.join('')
        if(literals.indexOf(contentstr) > -1) {
          mode = KEYWORD
        } else if(builtins.indexOf(contentstr) > -1) {
          mode = BUILTIN
        } else {
          mode = IDENT
        }
        token(content.join(''))
        mode = NORMAL
        return i
      }
      content.push(c)
      last = c
      return i + 1
    }
  }
  
  },{"./lib/builtins":188,"./lib/literals":189,"./lib/operators":190}],188:[function(require,module,exports){
  module.exports = [
      'gl_Position'
    , 'gl_PointSize'
    , 'gl_ClipVertex'
    , 'gl_FragCoord'
    , 'gl_FrontFacing'
    , 'gl_FragColor'
    , 'gl_FragData'
    , 'gl_FragDepth'
    , 'gl_Color'
    , 'gl_SecondaryColor'
    , 'gl_Normal'
    , 'gl_Vertex'
    , 'gl_MultiTexCoord0'
    , 'gl_MultiTexCoord1'
    , 'gl_MultiTexCoord2'
    , 'gl_MultiTexCoord3'
    , 'gl_MultiTexCoord4'
    , 'gl_MultiTexCoord5'
    , 'gl_MultiTexCoord6'
    , 'gl_MultiTexCoord7'
    , 'gl_FogCoord'
    , 'gl_MaxLights'
    , 'gl_MaxClipPlanes'
    , 'gl_MaxTextureUnits'
    , 'gl_MaxTextureCoords'
    , 'gl_MaxVertexAttribs'
    , 'gl_MaxVertexUniformComponents'
    , 'gl_MaxVaryingFloats'
    , 'gl_MaxVertexTextureImageUnits'
    , 'gl_MaxCombinedTextureImageUnits'
    , 'gl_MaxTextureImageUnits'
    , 'gl_MaxFragmentUniformComponents'
    , 'gl_MaxDrawBuffers'
    , 'gl_ModelViewMatrix'
    , 'gl_ProjectionMatrix'
    , 'gl_ModelViewProjectionMatrix'
    , 'gl_TextureMatrix'
    , 'gl_NormalMatrix'
    , 'gl_ModelViewMatrixInverse'
    , 'gl_ProjectionMatrixInverse'
    , 'gl_ModelViewProjectionMatrixInverse'
    , 'gl_TextureMatrixInverse'
    , 'gl_ModelViewMatrixTranspose'
    , 'gl_ProjectionMatrixTranspose'
    , 'gl_ModelViewProjectionMatrixTranspose'
    , 'gl_TextureMatrixTranspose'
    , 'gl_ModelViewMatrixInverseTranspose'
    , 'gl_ProjectionMatrixInverseTranspose'
    , 'gl_ModelViewProjectionMatrixInverseTranspose'
    , 'gl_TextureMatrixInverseTranspose'
    , 'gl_NormalScale'
    , 'gl_DepthRangeParameters'
    , 'gl_DepthRange'
    , 'gl_ClipPlane'
    , 'gl_PointParameters'
    , 'gl_Point'
    , 'gl_MaterialParameters'
    , 'gl_FrontMaterial'
    , 'gl_BackMaterial'
    , 'gl_LightSourceParameters'
    , 'gl_LightSource'
    , 'gl_LightModelParameters'
    , 'gl_LightModel'
    , 'gl_LightModelProducts'
    , 'gl_FrontLightModelProduct'
    , 'gl_BackLightModelProduct'
    , 'gl_LightProducts'
    , 'gl_FrontLightProduct'
    , 'gl_BackLightProduct'
    , 'gl_FogParameters'
    , 'gl_Fog'
    , 'gl_TextureEnvColor'
    , 'gl_EyePlaneS'
    , 'gl_EyePlaneT'
    , 'gl_EyePlaneR'
    , 'gl_EyePlaneQ'
    , 'gl_ObjectPlaneS'
    , 'gl_ObjectPlaneT'
    , 'gl_ObjectPlaneR'
    , 'gl_ObjectPlaneQ'
    , 'gl_FrontColor'
    , 'gl_BackColor'
    , 'gl_FrontSecondaryColor'
    , 'gl_BackSecondaryColor'
    , 'gl_TexCoord'
    , 'gl_FogFragCoord'
    , 'gl_Color'
    , 'gl_SecondaryColor'
    , 'gl_TexCoord'
    , 'gl_FogFragCoord'
    , 'gl_PointCoord'
    , 'radians'
    , 'degrees'
    , 'sin'
    , 'cos'
    , 'tan'
    , 'asin'
    , 'acos'
    , 'atan'
    , 'pow'
    , 'exp'
    , 'log'
    , 'exp2'
    , 'log2'
    , 'sqrt'
    , 'inversesqrt'
    , 'abs'
    , 'sign'
    , 'floor'
    , 'ceil'
    , 'fract'
    , 'mod'
    , 'min'
    , 'max'
    , 'clamp'
    , 'mix'
    , 'step'
    , 'smoothstep'
    , 'length'
    , 'distance'
    , 'dot'
    , 'cross'
    , 'normalize'
    , 'faceforward'
    , 'reflect'
    , 'refract'
    , 'matrixCompMult'
    , 'lessThan'
    , 'lessThanEqual'
    , 'greaterThan'
    , 'greaterThanEqual'
    , 'equal'
    , 'notEqual'
    , 'any'
    , 'all'
    , 'not'
    , 'texture2D'
    , 'texture2DProj'
    , 'texture2DLod'
    , 'texture2DProjLod'
    , 'textureCube'
    , 'textureCubeLod'
    , 'dFdx'
    , 'dFdy'
  ]
  
  },{}],189:[function(require,module,exports){
  module.exports = [
    // current
      'precision'
    , 'highp'
    , 'mediump'
    , 'lowp'
    , 'attribute'
    , 'const'
    , 'uniform'
    , 'varying'
    , 'break'
    , 'continue'
    , 'do'
    , 'for'
    , 'while'
    , 'if'
    , 'else'
    , 'in'
    , 'out'
    , 'inout'
    , 'float'
    , 'int'
    , 'void'
    , 'bool'
    , 'true'
    , 'false'
    , 'discard'
    , 'return'
    , 'mat2'
    , 'mat3'
    , 'mat4'
    , 'vec2'
    , 'vec3'
    , 'vec4'
    , 'ivec2'
    , 'ivec3'
    , 'ivec4'
    , 'bvec2'
    , 'bvec3'
    , 'bvec4'
    , 'sampler1D'
    , 'sampler2D'
    , 'sampler3D'
    , 'samplerCube'
    , 'sampler1DShadow'
    , 'sampler2DShadow'
    , 'struct'
  
    // future
    , 'asm'
    , 'class'
    , 'union'
    , 'enum'
    , 'typedef'
    , 'template'
    , 'this'
    , 'packed'
    , 'goto'
    , 'switch'
    , 'default'
    , 'inline'
    , 'noinline'
    , 'volatile'
    , 'public'
    , 'static'
    , 'extern'
    , 'external'
    , 'interface'
    , 'long'
    , 'short'
    , 'double'
    , 'half'
    , 'fixed'
    , 'unsigned'
    , 'input'
    , 'output'
    , 'hvec2'
    , 'hvec3'
    , 'hvec4'
    , 'dvec2'
    , 'dvec3'
    , 'dvec4'
    , 'fvec2'
    , 'fvec3'
    , 'fvec4'
    , 'sampler2DRect'
    , 'sampler3DRect'
    , 'sampler2DRectShadow'
    , 'sizeof'
    , 'cast'
    , 'namespace'
    , 'using'
  ]
  
  },{}],190:[function(require,module,exports){
  module.exports = [
      '<<='
    , '>>='
    , '++'
    , '--'
    , '<<'
    , '>>'
    , '<='
    , '>='
    , '=='
    , '!='
    , '&&'
    , '||'
    , '+='
    , '-='
    , '*='
    , '/='
    , '%='
    , '&='
    , '^^'
    , '^='
    , '|='
    , '('
    , ')'
    , '['
    , ']'
    , '.'
    , '!'
    , '~'
    , '*'
    , '/'
    , '%'
    , '+'
    , '-'
    , '<'
    , '>'
    , '&'
    , '^'
    , '|'
    , '?'
    , ':'
    , '='
    , ','
    , ';'
    , '{'
    , '}'
  ]
  
  },{}],191:[function(require,module,exports){
  var tokenize = require('./index')
  
  module.exports = tokenizeString
  
  function tokenizeString(str) {
    var generator = tokenize()
    var tokens = []
  
    tokens = tokens.concat(generator(str))
    tokens = tokens.concat(generator(null))
  
    return tokens
  }
  
  },{"./index":187}],192:[function(require,module,exports){
  var gkey = require('gkey/generic')
  
  function noop(){}
  
  var getGamepads =
      navigator.getGamepads ? function() { return navigator.getGamepads() }
    : navigator.mozGetGamepads ? function() { return navigator.mozGetGamepads() }
    : navigator.webkitGetGamepads ? function() { return navigator.webkitGetGamepads() }
    : noop
  
  module.exports = controller
  controller.supported = getGamepads !== noop
  
  function controller(index, controls) {
    var self = {}
      , gamepads = getGamepads()
      , enabled = []
  
    if (typeof index !== 'number') {
      controls = index
      index = 0
    }
    controls = controls || {}
  
    function poll() {
      var gamepad = getGamepads()[index]
  
      self.enabled = !!gamepad
      if (!self.enabled) return
  
      var buttons = gamepad.buttons
        , axes = gamepad.axes
        , bLength = buttons.length
        , aLength = axes.length
        , button
        , axis
  
      for (var a = 0; a < aLength; a += 1) {
        axis = controls[gkey.axes[a]]
        if (!axis) continue
        self.inputs[axis] = axes[a]
      }
  
      for (var b = 0; b < bLength; b += 1) {
        button = controls[gkey.buttons[b]]
        if (!button) continue
        self.inputs[button] = buttons[b]
      }
    }
  
    function createGamepad() {
      var gamepad = getGamepads()[index]
        , controller = {}
  
      Object.keys(controls).forEach(function(key) {
        var name = controls[key]
        controller[name] = 0
      })
  
      return controller
    }
  
    self.poll = poll
    self.inputs = createGamepad()
    self.enabled = false
  
    self.poll()
  
    return self
  }
  
  },{"gkey/generic":58}],193:[function(require,module,exports){
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var nBits = -7
    var i = isLE ? (nBytes - 1) : 0
    var d = isLE ? -1 : 1
    var s = buffer[offset + i]
  
    i += d
  
    e = s & ((1 << (-nBits)) - 1)
    s >>= (-nBits)
    nBits += eLen
    for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    m = e & ((1 << (-nBits)) - 1)
    e >>= (-nBits)
    nBits += mLen
    for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
  
    if (e === 0) {
      e = 1 - eBias
    } else if (e === eMax) {
      return m ? NaN : ((s ? -1 : 1) * Infinity)
    } else {
      m = m + Math.pow(2, mLen)
      e = e - eBias
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
  }
  
  exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c
    var eLen = nBytes * 8 - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
    var i = isLE ? 0 : (nBytes - 1)
    var d = isLE ? 1 : -1
    var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
  
    value = Math.abs(value)
  
    if (isNaN(value) || value === Infinity) {
      m = isNaN(value) ? 1 : 0
      e = eMax
    } else {
      e = Math.floor(Math.log(value) / Math.LN2)
      if (value * (c = Math.pow(2, -e)) < 1) {
        e--
        c *= 2
      }
      if (e + eBias >= 1) {
        value += rt / c
      } else {
        value += rt * Math.pow(2, 1 - eBias)
      }
      if (value * c >= 2) {
        e++
        c /= 2
      }
  
      if (e + eBias >= eMax) {
        m = 0
        e = eMax
      } else if (e + eBias >= 1) {
        m = (value * c - 1) * Math.pow(2, mLen)
        e = e + eBias
      } else {
        m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
        e = 0
      }
    }
  
    for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
  
    e = (e << mLen) | m
    eLen += mLen
    for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
  
    buffer[offset + i - d] |= s * 128
  }
  
  },{}],194:[function(require,module,exports){
  if (typeof Object.create === 'function') {
    // implementation from standard node.js 'util' module
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      ctor.prototype = Object.create(superCtor.prototype, {
        constructor: {
          value: ctor,
          enumerable: false,
          writable: true,
          configurable: true
        }
      });
    };
  } else {
    // old school shim for old browsers
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      var TempCtor = function () {}
      TempCtor.prototype = superCtor.prototype
      ctor.prototype = new TempCtor()
      ctor.prototype.constructor = ctor
    }
  }
  
  },{}],195:[function(require,module,exports){
  "use strict"
  
  function iota(n) {
    var result = new Array(n)
    for(var i=0; i<n; ++i) {
      result[i] = i
    }
    return result
  }
  
  module.exports = iota
  },{}],196:[function(require,module,exports){
  
  /**
   * isArray
   */
  
  var isArray = Array.isArray;
  
  /**
   * toString
   */
  
  var str = Object.prototype.toString;
  
  /**
   * Whether or not the given `val`
   * is an array.
   *
   * example:
   *
   *        isArray([]);
   *        // > true
   *        isArray(arguments);
   *        // > false
   *        isArray('');
   *        // > false
   *
   * @param {mixed} val
   * @return {bool}
   */
  
  module.exports = isArray || function (val) {
    return !! val && '[object Array]' == str.call(val);
  };
  
  },{}],197:[function(require,module,exports){
  /**
   * Determine if an object is Buffer
   *
   * Author:   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * License:  MIT
   *
   * `npm install is-buffer`
   */
  
  module.exports = function (obj) {
    return !!(obj != null &&
      (obj._isBuffer || // For Safari 5-7 (missing Object.prototype.constructor)
        (obj.constructor &&
        typeof obj.constructor.isBuffer === 'function' &&
        obj.constructor.isBuffer(obj))
      ))
  }
  
  },{}],198:[function(require,module,exports){
  module.exports = isFunction
  
  var toString = Object.prototype.toString
  
  function isFunction (fn) {
    var string = toString.call(fn)
    return string === '[object Function]' ||
      (typeof fn === 'function' && string !== '[object RegExp]') ||
      (typeof window !== 'undefined' &&
       // IE8 and below
       (fn === window.setTimeout ||
        fn === window.alert ||
        fn === window.confirm ||
        fn === window.prompt))
  };
  
  },{}],199:[function(require,module,exports){
  module.exports      = isTypedArray
  isTypedArray.strict = isStrictTypedArray
  isTypedArray.loose  = isLooseTypedArray
  
  var toString = Object.prototype.toString
  var names = {
      '[object Int8Array]': true
    , '[object Int16Array]': true
    , '[object Int32Array]': true
    , '[object Uint8Array]': true
    , '[object Uint16Array]': true
    , '[object Uint32Array]': true
    , '[object Float32Array]': true
    , '[object Float64Array]': true
  }
  
  function isTypedArray(arr) {
    return (
         isStrictTypedArray(arr)
      || isLooseTypedArray(arr)
    )
  }
  
  function isStrictTypedArray(arr) {
    return (
         arr instanceof Int8Array
      || arr instanceof Int16Array
      || arr instanceof Int32Array
      || arr instanceof Uint8Array
      || arr instanceof Uint16Array
      || arr instanceof Uint32Array
      || arr instanceof Float32Array
      || arr instanceof Float64Array
    )
  }
  
  function isLooseTypedArray(arr) {
    return names[toString.call(arr)]
  }
  
  },{}],200:[function(require,module,exports){
  module.exports = Array.isArray || function (arr) {
    return Object.prototype.toString.call(arr) == '[object Array]';
  };
  
  },{}],201:[function(require,module,exports){
  module.exports = function(arr) {
    if (!arr) return false
    if (!arr.dtype) return false
    var re = new RegExp('function View[0-9]+d(:?' + arr.dtype + ')+')
    return re.test(String(arr.constructor))
  }
  
  },{}],202:[function(require,module,exports){
  (function (process){
  var keys = require('vkey')
  var list = Object.keys(keys)
  var down = {}
  
  reset()
  
  module.exports = pressed
  
  if (process.browser) {
    window.addEventListener('keydown', keydown, false)
    window.addEventListener('keyup', keyup, false)
    window.addEventListener('blur', reset, false)
  }
  
  function pressed(key) {
    return key
      ? down[key]
      : down
  }
  
  function reset() {
    list.forEach(function(code) {
      down[keys[code]] = false
    })
  }
  
  function keyup(e) {
    down[keys[e.keyCode]] = false
  }
  
  function keydown(e) {
    down[keys[e.keyCode]] = true
  }
  
  }).call(this,require('_process'))
  },{"_process":11,"vkey":270}],203:[function(require,module,exports){
  "use strict"
  
  var compile = require("cwise-compiler")
  
  var EmptyProc = {
    body: "",
    args: [],
    thisVars: [],
    localVars: []
  }
  
  function fixup(x) {
    if(!x) {
      return EmptyProc
    }
    for(var i=0; i<x.args.length; ++i) {
      var a = x.args[i]
      if(i === 0) {
        x.args[i] = {name: a, lvalue:true, rvalue: !!x.rvalue, count:x.count||1 }
      } else {
        x.args[i] = {name: a, lvalue:false, rvalue:true, count: 1}
      }
    }
    if(!x.thisVars) {
      x.thisVars = []
    }
    if(!x.localVars) {
      x.localVars = []
    }
    return x
  }
  
  function pcompile(user_args) {
    return compile({
      args:     user_args.args,
      pre:      fixup(user_args.pre),
      body:     fixup(user_args.body),
      post:     fixup(user_args.proc),
      funcName: user_args.funcName
    })
  }
  
  function makeOp(user_args) {
    var args = []
    for(var i=0; i<user_args.args.length; ++i) {
      args.push("a"+i)
    }
    var wrapper = new Function("P", [
      "return function ", user_args.funcName, "_ndarrayops(", args.join(","), ") {P(", args.join(","), ");return a0}"
    ].join(""))
    return wrapper(pcompile(user_args))
  }
  
  var assign_ops = {
    add:  "+",
    sub:  "-",
    mul:  "*",
    div:  "/",
    mod:  "%",
    band: "&",
    bor:  "|",
    bxor: "^",
    lshift: "<<",
    rshift: ">>",
    rrshift: ">>>"
  }
  ;(function(){
    for(var id in assign_ops) {
      var op = assign_ops[id]
      exports[id] = makeOp({
        args: ["array","array","array"],
        body: {args:["a","b","c"],
               body: "a=b"+op+"c"},
        funcName: id
      })
      exports[id+"eq"] = makeOp({
        args: ["array","array"],
        body: {args:["a","b"],
               body:"a"+op+"=b"},
        rvalue: true,
        funcName: id+"eq"
      })
      exports[id+"s"] = makeOp({
        args: ["array", "array", "scalar"],
        body: {args:["a","b","s"],
               body:"a=b"+op+"s"},
        funcName: id+"s"
      })
      exports[id+"seq"] = makeOp({
        args: ["array","scalar"],
        body: {args:["a","s"],
               body:"a"+op+"=s"},
        rvalue: true,
        funcName: id+"seq"
      })
    }
  })();
  
  var unary_ops = {
    not: "!",
    bnot: "~",
    neg: "-",
    recip: "1.0/"
  }
  ;(function(){
    for(var id in unary_ops) {
      var op = unary_ops[id]
      exports[id] = makeOp({
        args: ["array", "array"],
        body: {args:["a","b"],
               body:"a="+op+"b"},
        funcName: id
      })
      exports[id+"eq"] = makeOp({
        args: ["array"],
        body: {args:["a"],
               body:"a="+op+"a"},
        rvalue: true,
        count: 2,
        funcName: id+"eq"
      })
    }
  })();
  
  var binary_ops = {
    and: "&&",
    or: "||",
    eq: "===",
    neq: "!==",
    lt: "<",
    gt: ">",
    leq: "<=",
    geq: ">="
  }
  ;(function() {
    for(var id in binary_ops) {
      var op = binary_ops[id]
      exports[id] = makeOp({
        args: ["array","array","array"],
        body: {args:["a", "b", "c"],
               body:"a=b"+op+"c"},
        funcName: id
      })
      exports[id+"s"] = makeOp({
        args: ["array","array","scalar"],
        body: {args:["a", "b", "s"],
               body:"a=b"+op+"s"},
        funcName: id+"s"
      })
      exports[id+"eq"] = makeOp({
        args: ["array", "array"],
        body: {args:["a", "b"],
               body:"a=a"+op+"b"},
        rvalue:true,
        count:2,
        funcName: id+"eq"
      })
      exports[id+"seq"] = makeOp({
        args: ["array", "scalar"],
        body: {args:["a","s"],
               body:"a=a"+op+"s"},
        rvalue:true,
        count:2,
        funcName: id+"seq"
      })
    }
  })();
  
  var math_unary = [
    "abs",
    "acos",
    "asin",
    "atan",
    "ceil",
    "cos",
    "exp",
    "floor",
    "log",
    "round",
    "sin",
    "sqrt",
    "tan"
  ]
  ;(function() {
    for(var i=0; i<math_unary.length; ++i) {
      var f = math_unary[i]
      exports[f] = makeOp({
                      args: ["array", "array"],
                      pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                      body: {args:["a","b"], body:"a=this_f(b)", thisVars:["this_f"]},
                      funcName: f
                    })
      exports[f+"eq"] = makeOp({
                        args: ["array"],
                        pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                        body: {args: ["a"], body:"a=this_f(a)", thisVars:["this_f"]},
                        rvalue: true,
                        count: 2,
                        funcName: f+"eq"
                      })
    }
  })();
  
  var math_comm = [
    "max",
    "min",
    "atan2",
    "pow"
  ]
  ;(function(){
    for(var i=0; i<math_comm.length; ++i) {
      var f= math_comm[i]
      exports[f] = makeOp({
                    args:["array", "array", "array"],
                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                    body: {args:["a","b","c"], body:"a=this_f(b,c)", thisVars:["this_f"]},
                    funcName: f
                  })
      exports[f+"s"] = makeOp({
                    args:["array", "array", "scalar"],
                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                    body: {args:["a","b","c"], body:"a=this_f(b,c)", thisVars:["this_f"]},
                    funcName: f+"s"
                    })
      exports[f+"eq"] = makeOp({ args:["array", "array"],
                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                    body: {args:["a","b"], body:"a=this_f(a,b)", thisVars:["this_f"]},
                    rvalue: true,
                    count: 2,
                    funcName: f+"eq"
                    })
      exports[f+"seq"] = makeOp({ args:["array", "scalar"],
                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                    body: {args:["a","b"], body:"a=this_f(a,b)", thisVars:["this_f"]},
                    rvalue:true,
                    count:2,
                    funcName: f+"seq"
                    })
    }
  })();
  
  var math_noncomm = [
    "atan2",
    "pow"
  ]
  ;(function(){
    for(var i=0; i<math_noncomm.length; ++i) {
      var f= math_noncomm[i]
      exports[f+"op"] = makeOp({
                    args:["array", "array", "array"],
                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                    body: {args:["a","b","c"], body:"a=this_f(c,b)", thisVars:["this_f"]},
                    funcName: f+"op"
                  })
      exports[f+"ops"] = makeOp({
                    args:["array", "array", "scalar"],
                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                    body: {args:["a","b","c"], body:"a=this_f(c,b)", thisVars:["this_f"]},
                    funcName: f+"ops"
                    })
      exports[f+"opeq"] = makeOp({ args:["array", "array"],
                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                    body: {args:["a","b"], body:"a=this_f(b,a)", thisVars:["this_f"]},
                    rvalue: true,
                    count: 2,
                    funcName: f+"opeq"
                    })
      exports[f+"opseq"] = makeOp({ args:["array", "scalar"],
                    pre: {args:[], body:"this_f=Math."+f, thisVars:["this_f"]},
                    body: {args:["a","b"], body:"a=this_f(b,a)", thisVars:["this_f"]},
                    rvalue:true,
                    count:2,
                    funcName: f+"opseq"
                    })
    }
  })();
  
  exports.any = compile({
    args:["array"],
    pre: EmptyProc,
    body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "if(a){return true}", localVars: [], thisVars: []},
    post: {args:[], localVars:[], thisVars:[], body:"return false"},
    funcName: "any"
  })
  
  exports.all = compile({
    args:["array"],
    pre: EmptyProc,
    body: {args:[{name:"x", lvalue:false, rvalue:true, count:1}], body: "if(!x){return false}", localVars: [], thisVars: []},
    post: {args:[], localVars:[], thisVars:[], body:"return true"},
    funcName: "all"
  })
  
  exports.sum = compile({
    args:["array"],
    pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
    body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "this_s+=a", localVars: [], thisVars: ["this_s"]},
    post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
    funcName: "sum"
  })
  
  exports.prod = compile({
    args:["array"],
    pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=1"},
    body: {args:[{name:"a", lvalue:false, rvalue:true, count:1}], body: "this_s*=a", localVars: [], thisVars: ["this_s"]},
    post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
    funcName: "prod"
  })
  
  exports.norm2squared = compile({
    args:["array"],
    pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
    body: {args:[{name:"a", lvalue:false, rvalue:true, count:2}], body: "this_s+=a*a", localVars: [], thisVars: ["this_s"]},
    post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
    funcName: "norm2squared"
  })
    
  exports.norm2 = compile({
    args:["array"],
    pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
    body: {args:[{name:"a", lvalue:false, rvalue:true, count:2}], body: "this_s+=a*a", localVars: [], thisVars: ["this_s"]},
    post: {args:[], localVars:[], thisVars:["this_s"], body:"return Math.sqrt(this_s)"},
    funcName: "norm2"
  })
    
  
  exports.norminf = compile({
    args:["array"],
    pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
    body: {args:[{name:"a", lvalue:false, rvalue:true, count:4}], body:"if(-a>this_s){this_s=-a}else if(a>this_s){this_s=a}", localVars: [], thisVars: ["this_s"]},
    post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
    funcName: "norminf"
  })
  
  exports.norm1 = compile({
    args:["array"],
    pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"},
    body: {args:[{name:"a", lvalue:false, rvalue:true, count:3}], body: "this_s+=a<0?-a:a", localVars: [], thisVars: ["this_s"]},
    post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"},
    funcName: "norm1"
  })
  
  exports.sup = compile({
    args: [ "array" ],
    pre:
     { body: "this_h=-Infinity",
       args: [],
       thisVars: [ "this_h" ],
       localVars: [] },
    body:
     { body: "if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_",
       args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ],
       thisVars: [ "this_h" ],
       localVars: [] },
    post:
     { body: "return this_h",
       args: [],
       thisVars: [ "this_h" ],
       localVars: [] }
   })
  
  exports.inf = compile({
    args: [ "array" ],
    pre:
     { body: "this_h=Infinity",
       args: [],
       thisVars: [ "this_h" ],
       localVars: [] },
    body:
     { body: "if(_inline_1_arg0_<this_h)this_h=_inline_1_arg0_",
       args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ],
       thisVars: [ "this_h" ],
       localVars: [] },
    post:
     { body: "return this_h",
       args: [],
       thisVars: [ "this_h" ],
       localVars: [] }
   })
  
  exports.argmin = compile({
    args:["index","array","shape"],
    pre:{
      body:"{this_v=Infinity;this_i=_inline_0_arg2_.slice(0)}",
      args:[
        {name:"_inline_0_arg0_",lvalue:false,rvalue:false,count:0},
        {name:"_inline_0_arg1_",lvalue:false,rvalue:false,count:0},
        {name:"_inline_0_arg2_",lvalue:false,rvalue:true,count:1}
        ],
      thisVars:["this_i","this_v"],
      localVars:[]},
    body:{
      body:"{if(_inline_1_arg1_<this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",
      args:[
        {name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2},
        {name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}],
      thisVars:["this_i","this_v"],
      localVars:["_inline_1_k"]},
    post:{
      body:"{return this_i}",
      args:[],
      thisVars:["this_i"],
      localVars:[]}
  })
  
  exports.argmax = compile({
    args:["index","array","shape"],
    pre:{
      body:"{this_v=-Infinity;this_i=_inline_0_arg2_.slice(0)}",
      args:[
        {name:"_inline_0_arg0_",lvalue:false,rvalue:false,count:0},
        {name:"_inline_0_arg1_",lvalue:false,rvalue:false,count:0},
        {name:"_inline_0_arg2_",lvalue:false,rvalue:true,count:1}
        ],
      thisVars:["this_i","this_v"],
      localVars:[]},
    body:{
      body:"{if(_inline_1_arg1_>this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}",
      args:[
        {name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2},
        {name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}],
      thisVars:["this_i","this_v"],
      localVars:["_inline_1_k"]},
    post:{
      body:"{return this_i}",
      args:[],
      thisVars:["this_i"],
      localVars:[]}
  })  
  
  exports.random = makeOp({
    args: ["array"],
    pre: {args:[], body:"this_f=Math.random", thisVars:["this_f"]},
    body: {args: ["a"], body:"a=this_f()", thisVars:["this_f"]},
    funcName: "random"
  })
  
  exports.assign = makeOp({
    args:["array", "array"],
    body: {args:["a", "b"], body:"a=b"},
    funcName: "assign" })
  
  exports.assigns = makeOp({
    args:["array", "scalar"],
    body: {args:["a", "b"], body:"a=b"},
    funcName: "assigns" })
  
  
  exports.equals = compile({
    args:["array", "array"],
    pre: EmptyProc,
    body: {args:[{name:"x", lvalue:false, rvalue:true, count:1},
                 {name:"y", lvalue:false, rvalue:true, count:1}], 
          body: "if(x!==y){return false}", 
          localVars: [], 
          thisVars: []},
    post: {args:[], localVars:[], thisVars:[], body:"return true"},
    funcName: "equals"
  })
  
  
  
  },{"cwise-compiler":44}],204:[function(require,module,exports){
  var iota = require("iota-array")
  var isBuffer = require("is-buffer")
  
  var hasTypedArrays  = ((typeof Float64Array) !== "undefined")
  
  function compare1st(a, b) {
    return a[0] - b[0]
  }
  
  function order() {
    var stride = this.stride
    var terms = new Array(stride.length)
    var i
    for(i=0; i<terms.length; ++i) {
      terms[i] = [Math.abs(stride[i]), i]
    }
    terms.sort(compare1st)
    var result = new Array(terms.length)
    for(i=0; i<result.length; ++i) {
      result[i] = terms[i][1]
    }
    return result
  }
  
  function compileConstructor(dtype, dimension) {
    var className = ["View", dimension, "d", dtype].join("")
    if(dimension < 0) {
      className = "View_Nil" + dtype
    }
    var useGetters = (dtype === "generic")
  
    if(dimension === -1) {
      //Special case for trivial arrays
      var code =
        "function "+className+"(a){this.data=a;};\
  var proto="+className+".prototype;\
  proto.dtype='"+dtype+"';\
  proto.index=function(){return -1};\
  proto.size=0;\
  proto.dimension=-1;\
  proto.shape=proto.stride=proto.order=[];\
  proto.lo=proto.hi=proto.transpose=proto.step=\
  function(){return new "+className+"(this.data);};\
  proto.get=proto.set=function(){};\
  proto.pick=function(){return null};\
  return function construct_"+className+"(a){return new "+className+"(a);}"
      var procedure = new Function(code)
      return procedure()
    } else if(dimension === 0) {
      //Special case for 0d arrays
      var code =
        "function "+className+"(a,d) {\
  this.data = a;\
  this.offset = d\
  };\
  var proto="+className+".prototype;\
  proto.dtype='"+dtype+"';\
  proto.index=function(){return this.offset};\
  proto.dimension=0;\
  proto.size=1;\
  proto.shape=\
  proto.stride=\
  proto.order=[];\
  proto.lo=\
  proto.hi=\
  proto.transpose=\
  proto.step=function "+className+"_copy() {\
  return new "+className+"(this.data,this.offset)\
  };\
  proto.pick=function "+className+"_pick(){\
  return TrivialArray(this.data);\
  };\
  proto.valueOf=proto.get=function "+className+"_get(){\
  return "+(useGetters ? "this.data.get(this.offset)" : "this.data[this.offset]")+
  "};\
  proto.set=function "+className+"_set(v){\
  return "+(useGetters ? "this.data.set(this.offset,v)" : "this.data[this.offset]=v")+"\
  };\
  return function construct_"+className+"(a,b,c,d){return new "+className+"(a,d)}"
      var procedure = new Function("TrivialArray", code)
      return procedure(CACHED_CONSTRUCTORS[dtype][0])
    }
  
    var code = ["'use strict'"]
  
    //Create constructor for view
    var indices = iota(dimension)
    var args = indices.map(function(i) { return "i"+i })
    var index_str = "this.offset+" + indices.map(function(i) {
          return "this.stride[" + i + "]*i" + i
        }).join("+")
    var shapeArg = indices.map(function(i) {
        return "b"+i
      }).join(",")
    var strideArg = indices.map(function(i) {
        return "c"+i
      }).join(",")
    code.push(
      "function "+className+"(a," + shapeArg + "," + strideArg + ",d){this.data=a",
        "this.shape=[" + shapeArg + "]",
        "this.stride=[" + strideArg + "]",
        "this.offset=d|0}",
      "var proto="+className+".prototype",
      "proto.dtype='"+dtype+"'",
      "proto.dimension="+dimension)
  
    //view.size:
    code.push("Object.defineProperty(proto,'size',{get:function "+className+"_size(){\
  return "+indices.map(function(i) { return "this.shape["+i+"]" }).join("*"),
  "}})")
  
    //view.order:
    if(dimension === 1) {
      code.push("proto.order=[0]")
    } else {
      code.push("Object.defineProperty(proto,'order',{get:")
      if(dimension < 4) {
        code.push("function "+className+"_order(){")
        if(dimension === 2) {
          code.push("return (Math.abs(this.stride[0])>Math.abs(this.stride[1]))?[1,0]:[0,1]}})")
        } else if(dimension === 3) {
          code.push(
  "var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\
  if(s0>s1){\
  if(s1>s2){\
  return [2,1,0];\
  }else if(s0>s2){\
  return [1,2,0];\
  }else{\
  return [1,0,2];\
  }\
  }else if(s0>s2){\
  return [2,0,1];\
  }else if(s2>s1){\
  return [0,1,2];\
  }else{\
  return [0,2,1];\
  }}})")
        }
      } else {
        code.push("ORDER})")
      }
    }
  
    //view.set(i0, ..., v):
    code.push(
  "proto.set=function "+className+"_set("+args.join(",")+",v){")
    if(useGetters) {
      code.push("return this.data.set("+index_str+",v)}")
    } else {
      code.push("return this.data["+index_str+"]=v}")
    }
  
    //view.get(i0, ...):
    code.push("proto.get=function "+className+"_get("+args.join(",")+"){")
    if(useGetters) {
      code.push("return this.data.get("+index_str+")}")
    } else {
      code.push("return this.data["+index_str+"]}")
    }
  
    //view.index:
    code.push(
      "proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}")
  
    //view.hi():
    code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+
      indices.map(function(i) {
        return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("")
      }).join(",")+","+
      indices.map(function(i) {
        return "this.stride["+i + "]"
      }).join(",")+",this.offset)}")
  
    //view.lo():
    var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" })
    var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" })
    code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(","))
    for(var i=0; i<dimension; ++i) {
      code.push(
  "if(typeof i"+i+"==='number'&&i"+i+">=0){\
  d=i"+i+"|0;\
  b+=c"+i+"*d;\
  a"+i+"-=d}")
    }
    code.push("return new "+className+"(this.data,"+
      indices.map(function(i) {
        return "a"+i
      }).join(",")+","+
      indices.map(function(i) {
        return "c"+i
      }).join(",")+",b)}")
  
    //view.step():
    code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+
      indices.map(function(i) {
        return "a"+i+"=this.shape["+i+"]"
      }).join(",")+","+
      indices.map(function(i) {
        return "b"+i+"=this.stride["+i+"]"
      }).join(",")+",c=this.offset,d=0,ceil=Math.ceil")
    for(var i=0; i<dimension; ++i) {
      code.push(
  "if(typeof i"+i+"==='number'){\
  d=i"+i+"|0;\
  if(d<0){\
  c+=b"+i+"*(a"+i+"-1);\
  a"+i+"=ceil(-a"+i+"/d)\
  }else{\
  a"+i+"=ceil(a"+i+"/d)\
  }\
  b"+i+"*=d\
  }")
    }
    code.push("return new "+className+"(this.data,"+
      indices.map(function(i) {
        return "a" + i
      }).join(",")+","+
      indices.map(function(i) {
        return "b" + i
      }).join(",")+",c)}")
  
    //view.transpose():
    var tShape = new Array(dimension)
    var tStride = new Array(dimension)
    for(var i=0; i<dimension; ++i) {
      tShape[i] = "a[i"+i+"]"
      tStride[i] = "b[i"+i+"]"
    }
    code.push("proto.transpose=function "+className+"_transpose("+args+"){"+
      args.map(function(n,idx) { return n + "=(" + n + "===undefined?" + idx + ":" + n + "|0)"}).join(";"),
      "var a=this.shape,b=this.stride;return new "+className+"(this.data,"+tShape.join(",")+","+tStride.join(",")+",this.offset)}")
  
    //view.pick():
    code.push("proto.pick=function "+className+"_pick("+args+"){var a=[],b=[],c=this.offset")
    for(var i=0; i<dimension; ++i) {
      code.push("if(typeof i"+i+"==='number'&&i"+i+">=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}")
    }
    code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}")
  
    //Add return statement
    code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+
      indices.map(function(i) {
        return "shape["+i+"]"
      }).join(",")+","+
      indices.map(function(i) {
        return "stride["+i+"]"
      }).join(",")+",offset)}")
  
    //Compile procedure
    var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n"))
    return procedure(CACHED_CONSTRUCTORS[dtype], order)
  }
  
  function arrayDType(data) {
    if(isBuffer(data)) {
      return "buffer"
    }
    if(hasTypedArrays) {
      switch(Object.prototype.toString.call(data)) {
        case "[object Float64Array]":
          return "float64"
        case "[object Float32Array]":
          return "float32"
        case "[object Int8Array]":
          return "int8"
        case "[object Int16Array]":
          return "int16"
        case "[object Int32Array]":
          return "int32"
        case "[object Uint8Array]":
          return "uint8"
        case "[object Uint16Array]":
          return "uint16"
        case "[object Uint32Array]":
          return "uint32"
        case "[object Uint8ClampedArray]":
          return "uint8_clamped"
      }
    }
    if(Array.isArray(data)) {
      return "array"
    }
    return "generic"
  }
  
  var CACHED_CONSTRUCTORS = {
    "float32":[],
    "float64":[],
    "int8":[],
    "int16":[],
    "int32":[],
    "uint8":[],
    "uint16":[],
    "uint32":[],
    "array":[],
    "uint8_clamped":[],
    "buffer":[],
    "generic":[]
  }
  
  ;(function() {
    for(var id in CACHED_CONSTRUCTORS) {
      CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1))
    }
  });
  
  function wrappedNDArrayCtor(data, shape, stride, offset) {
    if(data === undefined) {
      var ctor = CACHED_CONSTRUCTORS.array[0]
      return ctor([])
    } else if(typeof data === "number") {
      data = [data]
    }
    if(shape === undefined) {
      shape = [ data.length ]
    }
    var d = shape.length
    if(stride === undefined) {
      stride = new Array(d)
      for(var i=d-1, sz=1; i>=0; --i) {
        stride[i] = sz
        sz *= shape[i]
      }
    }
    if(offset === undefined) {
      offset = 0
      for(var i=0; i<d; ++i) {
        if(stride[i] < 0) {
          offset -= (shape[i]-1)*stride[i]
        }
      }
    }
    var dtype = arrayDType(data)
    var ctor_list = CACHED_CONSTRUCTORS[dtype]
    while(ctor_list.length <= d+1) {
      ctor_list.push(compileConstructor(dtype, ctor_list.length-1))
    }
    var ctor = ctor_list[d+1]
    return ctor(data, shape, stride, offset)
  }
  
  module.exports = wrappedNDArrayCtor
  
  },{"iota-array":195,"is-buffer":197}],205:[function(require,module,exports){
  var EPSILON = 1e-6;
  
  //Estimate the vertex normals of a mesh
  exports.vertexNormals = function(faces, positions) {
    
    var N         = positions.length;
    var normals   = new Array(N);
    
    //Initialize normal array
    for(var i=0; i<N; ++i) {
      normals[i] = [0.0, 0.0, 0.0];
    }
    
    //Walk over all the faces and add per-vertex contribution to normal weights
    for(var i=0; i<faces.length; ++i) {
      var f = faces[i];
      var p = 0;
      var c = f[f.length-1];
      var n = f[0];
      for(var j=0; j<f.length; ++j) {
      
        //Shift indices back
        p = c;
        c = n;
        n = f[(j+1) % f.length];
      
        var v0 = positions[p];
        var v1 = positions[c];
        var v2 = positions[n];
        
        //Compute infineteismal arcs
        var d01 = new Array(3);
        var m01 = 0.0;
        var d21 = new Array(3);
        var m21 = 0.0;
        for(var k=0; k<3; ++k) {
          d01[k] = v0[k]  - v1[k];
          m01   += d01[k] * d01[k];
          d21[k] = v2[k]  - v1[k];
          m21   += d21[k] * d21[k];
        }
  
        //Accumulate values in normal
        if(m01 * m21 > EPSILON) {
          var norm = normals[c];
          var w = 1.0 / Math.sqrt(m01 * m21);
          for(var k=0; k<3; ++k) {
            var u = (k+1)%3;
            var v = (k+2)%3;
            norm[k] += w * (d21[u] * d01[v] - d21[v] * d01[u]);
          }
        }
      }
    }
    
    //Scale all normals to unit length
    for(var i=0; i<N; ++i) {
      var norm = normals[i];
      var m = 0.0;
      for(var k=0; k<3; ++k) {
        m += norm[k] * norm[k];
      }
      if(m > EPSILON) {
        var w = 1.0 / Math.sqrt(m);
        for(var k=0; k<3; ++k) {
          norm[k] *= w;
        }
      } else {
        for(var k=0; k<3; ++k) {
          norm[k] = 0.0;
        }
      }
    }
  
    //Return the resulting set of patches
    return normals;
  }
  
  //Compute face normals of a mesh
  exports.faceNormals = function(faces, positions) {
    var N         = faces.length;
    var normals   = new Array(N);
    
    for(var i=0; i<N; ++i) {
      var f = faces[i];
      var pos = new Array(3);
      for(var j=0; j<3; ++j) {
        pos[j] = positions[f[j]];
      }
      
      var d01 = new Array(3);
      var d21 = new Array(3);
      for(var j=0; j<3; ++j) {
        d01[j] = pos[1][j] - pos[0][j];
        d21[j] = pos[2][j] - pos[0][j];
      }
      
      var n = new Array(3);
      var l = 0.0;
      for(var j=0; j<3; ++j) {
        var u = (j+1)%3;
        var v = (j+2)%3;
        n[j] = d01[u] * d21[v] - d01[v] * d21[u];
        l += n[j] * n[j];
      }
      if(l > EPSILON) {
        l = 1.0 / Math.sqrt(l);
      } else {
        l = 0.0;
      }
      for(var j=0; j<3; ++j) {
        n[j] *= l;
      }
      normals[i] = n;
    }
    return normals;
  }
  
  
  
  },{}],206:[function(require,module,exports){
  var stream = require('stream');
  var split = require('split');
  var xhr = require('xhr');
  
  
  function ObjLoader() {
  
    this.vertices = [];
    this.normals = [];
    this.textureCoords = [];
    this.faces = [];
    this.facesMaterialsIndex = [{materialName: null, materialStartIndex: 0}];
    this.materials = [];
  
  }
  
  ObjLoader.prototype.load = function(objFilePath, mtlFilePath, callback) {
  
    var self = this;
  
    if(typeof mtlFilePath === "function") {
      callback = mtlFilePath;
      mtlFilePath = "";
    }
  
    xhr(objFilePath, function (err, resp, objFileString) {
      if(err) {
        /*Error Handling*/
        callback(err);
      }
      /*Create readable stream to read obj file line by line*/
      var readable = self.createReadStream(objFileString);
  
      readable
        .pipe(split())
        .on('data', function(line) {
          self.parseObj(line);
        })
        .on('end', function() {
  
          /*Start reading .mtl file*/
          if(typeof mtlFilePath === "string" && mtlFilePath !== "") {
            xhr(mtlFilePath, function (err, resp, mtlFileString) {
  
              if(err) {
                callback(err);
              }
  
              var currentMat = {};
              var readable = self.createReadStream(mtlFileString);
  
              readable
                .pipe(split())
                .on('data', function(line) {
                  currentMat = self.parseMtl(line, currentMat);
                })
                .on('end', function() {
                  if(currentMat.name) {
                    self.materials.push(currentMat);
                  }
                  /*Geometry and Materials*/
                  callback(
                    null,
                    {
                      vertices: self.vertices,
                      normals: self.normals,
                      textureCoords: self.textureCoords,
                      faces: self.faces,
                      facesMaterialsIndex: self.facesMaterialsIndex,
                      materials: self.materials
                    }
                  );
                })
                .on('err', function(err) {
                  /*Error Handling*/
                  callback(err)
                });
            });
          }
          else {
            /*Only Geometry*/
            callback(
              null,
              {
                vertices: self.vertices,
                normals: self.normals,
                textureCoords: self.textureCoords,
                faces: self.faces
              }
            );
          }
        })
        .on('err', function(err) {
          /*Error Handling*/
          callback(err);
        });
    });
  }
  
  
  ObjLoader.prototype.createReadStream = function(fileString) {
    var readable = new stream.Readable();
    readable._read = function noop() {};
    readable.push(fileString);
    readable.push(null);
    return readable;
  }
  
  
  ObjLoader.prototype.parseObj = function(line) {
  
    /*Not include comment*/
    var commentStart = line.indexOf("#");
    if(commentStart != -1) {
      line = line.substring(0, commentStart);
    }
    line = line.trim();
  
    var splitedLine = line.split(/\s+/);
  
    if(splitedLine[0] === 'v') {
      var vertex = [Number(splitedLine[1]), Number(splitedLine[2]), Number(splitedLine[3]), splitedLine[4]? 1 : Number(splitedLine[4])];
      this.vertices.push(vertex);
    }
    else if(splitedLine[0] === 'vt') {
      var textureCoord = [Number(splitedLine[1]), Number(splitedLine[2]), splitedLine[3]? 1 : Number(splitedLine[3])]
      this.textureCoords.push(textureCoord);
    }
    else if(splitedLine[0] === 'vn') {
      var normal = [Number(splitedLine[1]), Number(splitedLine[2]), Number(splitedLine[3])];
      this.normals.push(normal);
    }
    else if(splitedLine[0] === 'f') {
      var face = {
        indices: [],
        texture: [],
        normal: []
        };
  
      for(var i = 1; i < splitedLine.length; ++i) {
        var dIndex = splitedLine[i].indexOf('//');
        var splitedFaceIndices = splitedLine[i].split(/\W+/);
  
        if(dIndex > 0) {
          /*Vertex Normal Indices Without Texture Coordinate Indices*/
          face.indices.push(splitedFaceIndices[0]);
          face.normal.push(splitedFaceIndices[1]);
        }
        else {
          if(splitedFaceIndices.length === 1) {
            /*Vertex Indices*/
            face.indices.push(splitedFaceIndices[0]);
          }
          else if(splitedFaceIndices.length === 2) {
            /*Vertex Texture Coordinate Indices*/
            face.indices.push(splitedFaceIndices[0]);
            face.texture.push(splitedFaceIndices[1]);
          }
          else if(splitedFaceIndices.length === 3) {
            /*Vertex Normal Indices*/
            face.indices.push(splitedFaceIndices[0]);
            face.texture.push(splitedFaceIndices[1]);
            face.normal.push(splitedFaceIndices[2]);
          }
        }
      }
  
      this.faces.push(face);
    }
    else if(splitedLine[0] === "usemtl") {
      if(this.faces.length === 0) {
        this.facesMaterialsIndex[0].materialName = splitedLine[1];
      }
      else {
        var materialName = splitedLine[1];
        var materialStartIndex = this.faces.length;
  
        this.facesMaterialsIndex.push({materialName: materialName, materialStartIndex: materialStartIndex});
      }
    }
  }
  
  
  ObjLoader.prototype.parseMtl = function(line, currentMat) {
  
    /*Not include comment*/
    var commentStart = line.indexOf("#");
    if(commentStart != -1) {
      line = line.substring(0, commentStart);
    }
  
    line = line.trim();
    var splitedLine = line.split(/\s+/);
  
    if(splitedLine[0] === "newmtl") {
      if(currentMat.name) {
        this.materials.push(currentMat);
        currentMat = {};
      }
      currentMat.name = splitedLine[1];
    }
    else if(splitedLine[0] === "Ka") {
      currentMat.ambient = [];
      for(var i = 0; i < 3; ++i) {
        currentMat.ambient.push(splitedLine[i+1]);
      }
    }
    else if(splitedLine[0] === "Kd") {
      currentMat.diffuse = [];
      for(var i = 0; i < 3; ++i) {
        currentMat.diffuse.push(splitedLine[i+1]);
      }
    }
    else if(splitedLine[0] === "Ks") {
      currentMat.specular = [];
      for(var i = 0; i < 3; ++i) {
        currentMat.specular.push(splitedLine[i+1]);
      }
    }
    else if(splitedLine[0] === "Ns") {
      currentMat.specularExponent = splitedLine[1];
    }
    else if(splitedLine[0] === "d" || splitedLine[0] === "Tr") {
      currentMat.transparent = splitedLine[1];
    }
    else if(splitedLine[0] === "illum") {
      currentMat.illumMode = splitedLine[1];
    }
    else if(splitedLine[0] === "map_Ka") {
      currentMat.ambientMap = splitedLine[1];
    }
    else if(splitedLine[0] === "map_Kd") {
      currentMat.diffuseMap = splitedLine[1];
    }
    else if(splitedLine[0] === "map_Ks") {
      currentMat.specularMap = splitedLine[1];
    }
    else if(splitedLine[0] === "map_d") {
      currentMat.alphaMat = splitedLine[1];
    }
    else if(splitedLine[0] === "map_bump" || splitedLine[0] === "bump") {
      currentMat.bumpMap = splitedLine[1];
    }
    else if(splitedLine[0] === "disp") {
      currentMat.displacementMap = splitedLine[1];
    }
  
    return currentMat;
  }
  
  
  module.exports = ObjLoader;
  
  },{"split":256,"stream":258,"xhr":278}],207:[function(require,module,exports){
  'use strict';
  var propIsEnumerable = Object.prototype.propertyIsEnumerable;
  
  function ToObject(val) {
  	if (val == null) {
  		throw new TypeError('Object.assign cannot be called with null or undefined');
  	}
  
  	return Object(val);
  }
  
  function ownEnumerableKeys(obj) {
  	var keys = Object.getOwnPropertyNames(obj);
  
  	if (Object.getOwnPropertySymbols) {
  		keys = keys.concat(Object.getOwnPropertySymbols(obj));
  	}
  
  	return keys.filter(function (key) {
  		return propIsEnumerable.call(obj, key);
  	});
  }
  
  module.exports = Object.assign || function (target, source) {
  	var from;
  	var keys;
  	var to = ToObject(target);
  
  	for (var s = 1; s < arguments.length; s++) {
  		from = arguments[s];
  		keys = ownEnumerableKeys(Object(from));
  
  		for (var i = 0; i < keys.length; i++) {
  			to[keys[i]] = from[keys[i]];
  		}
  	}
  
  	return to;
  };
  
  },{}],208:[function(require,module,exports){
  module.exports = once
  
  once.proto = once(function () {
    Object.defineProperty(Function.prototype, 'once', {
      value: function () {
        return once(this)
      },
      configurable: true
    })
  })
  
  function once (fn) {
    var called = false
    return function () {
      if (called) return
      called = true
      return fn.apply(this, arguments)
    }
  }
  
  },{}],209:[function(require,module,exports){
  "use strict"
  
  var glm = require("gl-matrix")
  var vec3 = glm.vec3
  var mat3 = glm.mat3
  var mat4 = glm.mat4
  var quat = glm.quat
  
  //Scratch variables
  var scratch0 = new Float32Array(16)
  var scratch1 = new Float32Array(16)
  
  function OrbitCamera(rotation, center, distance) {
    this.rotation = rotation
    this.center   = center
    this.distance = distance
  }
  
  var proto = OrbitCamera.prototype
  
  proto.view = function(out) {
    if(!out) {
      out = mat4.create()
    }
    scratch1[0] = scratch1[1] = 0.0
    scratch1[2] = -this.distance
    mat4.fromRotationTranslation(out,
      quat.conjugate(scratch0, this.rotation),
      scratch1)
    mat4.translate(out, out, vec3.negate(scratch0, this.center))
    return out
  }
  
  proto.lookAt = function(eye, center, up) {
    mat4.lookAt(scratch0, eye, center, up)
    mat3.fromMat4(scratch0, scratch0)
    quat.fromMat3(this.rotation, scratch0)
    vec3.copy(this.center, center)
    this.distance = vec3.distance(eye, center)
  }
  
  proto.pan = function(dpan) {
    var d = this.distance
    scratch0[0] = -d*(dpan[0]||0)
    scratch0[1] =  d*(dpan[1]||0)
    scratch0[2] =  d*(dpan[2]||0)
    vec3.transformQuat(scratch0, scratch0, this.rotation)
    vec3.add(this.center, this.center, scratch0)
  }
  
  proto.zoom = function(d) {
    this.distance += d
    if(this.distance < 0.0) {
      this.distance = 0.0
    }
  }
  
  function quatFromVec(out, da) {
    var x = da[0]
    var y = da[1]
    var z = da[2]
    var s = x*x + y*y
    if(s > 1.0) {
      s = 1.0
    }
    out[0] = -da[0]
    out[1] =  da[1]
    out[2] =  da[2] || Math.sqrt(1.0 - s)
    out[3] =  0.0
  }
  
  proto.rotate = function(da, db) {
    quatFromVec(scratch0, da)
    quatFromVec(scratch1, db)
    quat.invert(scratch1, scratch1)
    quat.multiply(scratch0, scratch0, scratch1)
    if(quat.length(scratch0) < 1e-6) {
      return
    }
    quat.multiply(this.rotation, this.rotation, scratch0)
    quat.normalize(this.rotation, this.rotation)
  }
  
  function createOrbitCamera(eye, target, up) {
    eye     = eye     || [0,0,-1]
    target  = target  || [0,0,0]
    up      = up      || [0,1,0]
    var camera = new OrbitCamera(quat.create(), vec3.create(), 1.0)
    camera.lookAt(eye, target, up)
    return camera
  }
  
  module.exports = createOrbitCamera
  
  },{"gl-matrix":93}],210:[function(require,module,exports){
  /*!
   * pad-left <https://github.com/jonschlinkert/pad-left>
   *
   * Copyright (c) 2014-2015, Jon Schlinkert.
   * Licensed under the MIT license.
   */
  
  'use strict';
  
  var repeat = require('repeat-string');
  
  module.exports = function padLeft(str, num, ch) {
    ch = typeof ch !== 'undefined' ? (ch + '') : ' ';
    return repeat(ch, num) + str;
  };
  },{"repeat-string":255}],211:[function(require,module,exports){
  var trim = require('trim')
    , forEach = require('for-each')
    , isArray = function(arg) {
        return Object.prototype.toString.call(arg) === '[object Array]';
      }
  
  module.exports = function (headers) {
    if (!headers)
      return {}
  
    var result = {}
  
    forEach(
        trim(headers).split('\n')
      , function (row) {
          var index = row.indexOf(':')
            , key = trim(row.slice(0, index)).toLowerCase()
            , value = trim(row.slice(index + 1))
  
          if (typeof(result[key]) === 'undefined') {
            result[key] = value
          } else if (isArray(result[key])) {
            result[key].push(value)
          } else {
            result[key] = [ result[key], value ]
          }
        }
    )
  
    return result
  }
  },{"for-each":57,"trim":262}],212:[function(require,module,exports){
  (function (Buffer){
  /* jshint node: true */
  /* jslint asi: true */
  'use strict'
  
  var Dissolve = require('dissolve')
  var util = require('util')
  var assert = require('chai').assert
  
  /* Implemented with the help of http://mattebb.com/projects/bpython/pointcache/export_pc2.py */
  function PC2Parser () {
    Dissolve.call(this)
  
    // Read header(32 bytes)
    this.string('cacheSignatureString', 11).tap(checkEqual('cacheSignatureString', 'POINTCACHE2'))
    this.uint8('zero').tap(checkEqual('zero', 0))
    this.uint32le('fileVersion').tap(checkEqual('fileVersion', 1))
    this.uint32le('numPoints') // Number of points per sample
    this.floatle('startFrame') // First sampled frame
    this.floatle('sampleRate') // How frequently to sample (or skip) the frames
    this.uint32le('numSamples') // How many samples are stored in this file
  
    // Read raw data for positions
    this.tap(function () {
      this.vars.numFrames = this.vars.numSamples / this.vars.sampleRate
      this.buffer('raw', this.vars.numFrames * this.vars.numPoints * 12)
    })
  
    // Organize positions as nested, anonymous arrays
    // (could not do it with "loop")
    this.tap(function () {
      var raw = this.vars.raw
      delete this.vars.raw
  
      // "for frame in range(startFrame, startFrame+numSamples, sampleRate)"
      this.vars.frames = []
      for (var idx = 0; idx < this.vars.numFrames; idx++) {
        this.vars.frames.push(pointsArray(raw, idx * this.vars.numPoints * 12, this.vars.numPoints))
      }
    })
  
    // Read from buffer "buf", starting at position "offset", an array of "numPoints" positions (arrays of 3 floats)
    function pointsArray (buf, offset, numPoints) {
      var pointsData = []
      for (var i = offset; i < offset + numPoints * 12; i += 12) {
        pointsData.push([buf.readFloatLE(i + 0), buf.readFloatLE(i + 4), buf.readFloatLE(i + 8)])
      }
      return pointsData
    }
  
    // Emit result ("this" is a Transform stream)
    this.tap(function () {
      this.push(this.vars)
    })
  }
  
  util.inherits(PC2Parser, Dissolve)
  
  function checkEqual (varName, expected) {
    return function () {
      assert.equal(this.vars[varName], expected)
    }
  }
  
  function blockingParser (data) {
    var result
    var parser = new PC2Parser()
    parser.on('readable', function () {
      var pc2Data = parser.read()
      if (pc2Data) {
        result = pc2Data
      }
    })
    parser.write(!Buffer.isBuffer(data) ? new Buffer(data) : data)
    parser.end()
    return result
  }
  
  // Usage: see tests.js
  module.exports = {
    StreamingParser: PC2Parser,
    toObject: blockingParser
  }
  
  }).call(this,require("buffer").Buffer)
  },{"buffer":12,"chai":213,"dissolve":51,"util":269}],213:[function(require,module,exports){
  arguments[4][14][0].apply(exports,arguments)
  },{"./lib/chai":214,"C:\\Users\\Olivier\\Projets\\LD34\\PostLD34\\git\\LD34\\node_modules\\chai\\index.js":14}],214:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var used = []
    , exports = module.exports = {};
  
  /*!
   * Chai version
   */
  
  exports.version = '3.5.0';
  
  /*!
   * Assertion Error
   */
  
  exports.AssertionError = require('assertion-error');
  
  /*!
   * Utils for plugins (not exported)
   */
  
  var util = require('./chai/utils');
  
  /**
   * # .use(function)
   *
   * Provides a way to extend the internals of Chai
   *
   * @param {Function}
   * @returns {this} for chaining
   * @api public
   */
  
  exports.use = function (fn) {
    if (!~used.indexOf(fn)) {
      fn(this, util);
      used.push(fn);
    }
  
    return this;
  };
  
  /*!
   * Utility Functions
   */
  
  exports.util = util;
  
  /*!
   * Configuration
   */
  
  var config = require('./chai/config');
  exports.config = config;
  
  /*!
   * Primary `Assertion` prototype
   */
  
  var assertion = require('./chai/assertion');
  exports.use(assertion);
  
  /*!
   * Core Assertions
   */
  
  var core = require('./chai/core/assertions');
  exports.use(core);
  
  /*!
   * Expect interface
   */
  
  var expect = require('./chai/interface/expect');
  exports.use(expect);
  
  /*!
   * Should interface
   */
  
  var should = require('./chai/interface/should');
  exports.use(should);
  
  /*!
   * Assert interface
   */
  
  var assert = require('./chai/interface/assert');
  exports.use(assert);
  
  },{"./chai/assertion":215,"./chai/config":216,"./chai/core/assertions":217,"./chai/interface/assert":218,"./chai/interface/expect":219,"./chai/interface/should":220,"./chai/utils":234,"assertion-error":7}],215:[function(require,module,exports){
  module.exports=require(16)
  },{"./config":216,"C:\\Users\\Olivier\\Projets\\LD34\\PostLD34\\git\\LD34\\node_modules\\chai\\lib\\chai\\assertion.js":16}],216:[function(require,module,exports){
  module.exports=require(17)
  },{"C:\\Users\\Olivier\\Projets\\LD34\\PostLD34\\git\\LD34\\node_modules\\chai\\lib\\chai\\config.js":17}],217:[function(require,module,exports){
  /*!
   * chai
   * http://chaijs.com
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, _) {
    var Assertion = chai.Assertion
      , toString = Object.prototype.toString
      , flag = _.flag;
  
    /**
     * ### Language Chains
     *
     * The following are provided as chainable getters to
     * improve the readability of your assertions. They
     * do not provide testing capabilities unless they
     * have been overwritten by a plugin.
     *
     * **Chains**
     *
     * - to
     * - be
     * - been
     * - is
     * - that
     * - which
     * - and
     * - has
     * - have
     * - with
     * - at
     * - of
     * - same
     *
     * @name language chains
     * @namespace BDD
     * @api public
     */
  
    [ 'to', 'be', 'been'
    , 'is', 'and', 'has', 'have'
    , 'with', 'that', 'which', 'at'
    , 'of', 'same' ].forEach(function (chain) {
      Assertion.addProperty(chain, function () {
        return this;
      });
    });
  
    /**
     * ### .not
     *
     * Negates any of assertions following in the chain.
     *
     *     expect(foo).to.not.equal('bar');
     *     expect(goodFn).to.not.throw(Error);
     *     expect({ foo: 'baz' }).to.have.property('foo')
     *       .and.not.equal('bar');
     *
     * @name not
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('not', function () {
      flag(this, 'negate', true);
    });
  
    /**
     * ### .deep
     *
     * Sets the `deep` flag, later used by the `equal` and
     * `property` assertions.
     *
     *     expect(foo).to.deep.equal({ bar: 'baz' });
     *     expect({ foo: { bar: { baz: 'quux' } } })
     *       .to.have.deep.property('foo.bar.baz', 'quux');
     *
     * `.deep.property` special characters can be escaped
     * by adding two slashes before the `.` or `[]`.
     *
     *     var deepCss = { '.link': { '[target]': 42 }};
     *     expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
     *
     * @name deep
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('deep', function () {
      flag(this, 'deep', true);
    });
  
    /**
     * ### .any
     *
     * Sets the `any` flag, (opposite of the `all` flag)
     * later used in the `keys` assertion.
     *
     *     expect(foo).to.have.any.keys('bar', 'baz');
     *
     * @name any
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('any', function () {
      flag(this, 'any', true);
      flag(this, 'all', false)
    });
  
  
    /**
     * ### .all
     *
     * Sets the `all` flag (opposite of the `any` flag)
     * later used by the `keys` assertion.
     *
     *     expect(foo).to.have.all.keys('bar', 'baz');
     *
     * @name all
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('all', function () {
      flag(this, 'all', true);
      flag(this, 'any', false);
    });
  
    /**
     * ### .a(type)
     *
     * The `a` and `an` assertions are aliases that can be
     * used either as language chains or to assert a value's
     * type.
     *
     *     // typeof
     *     expect('test').to.be.a('string');
     *     expect({ foo: 'bar' }).to.be.an('object');
     *     expect(null).to.be.a('null');
     *     expect(undefined).to.be.an('undefined');
     *     expect(new Error).to.be.an('error');
     *     expect(new Promise).to.be.a('promise');
     *     expect(new Float32Array()).to.be.a('float32array');
     *     expect(Symbol()).to.be.a('symbol');
     *
     *     // es6 overrides
     *     expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo');
     *
     *     // language chain
     *     expect(foo).to.be.an.instanceof(Foo);
     *
     * @name a
     * @alias an
     * @param {String} type
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function an (type, msg) {
      if (msg) flag(this, 'message', msg);
      type = type.toLowerCase();
      var obj = flag(this, 'object')
        , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
  
      this.assert(
          type === _.type(obj)
        , 'expected #{this} to be ' + article + type
        , 'expected #{this} not to be ' + article + type
      );
    }
  
    Assertion.addChainableMethod('an', an);
    Assertion.addChainableMethod('a', an);
  
    /**
     * ### .include(value)
     *
     * The `include` and `contain` assertions can be used as either property
     * based language chains or as methods to assert the inclusion of an object
     * in an array or a substring in a string. When used as language chains,
     * they toggle the `contains` flag for the `keys` assertion.
     *
     *     expect([1,2,3]).to.include(2);
     *     expect('foobar').to.contain('foo');
     *     expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
     *
     * @name include
     * @alias contain
     * @alias includes
     * @alias contains
     * @param {Object|String|Number} obj
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function includeChainingBehavior () {
      flag(this, 'contains', true);
    }
  
    function include (val, msg) {
      _.expectTypes(this, ['array', 'object', 'string']);
  
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var expected = false;
  
      if (_.type(obj) === 'array' && _.type(val) === 'object') {
        for (var i in obj) {
          if (_.eql(obj[i], val)) {
            expected = true;
            break;
          }
        }
      } else if (_.type(val) === 'object') {
        if (!flag(this, 'negate')) {
          for (var k in val) new Assertion(obj).property(k, val[k]);
          return;
        }
        var subset = {};
        for (var k in val) subset[k] = obj[k];
        expected = _.eql(subset, val);
      } else {
        expected = (obj != undefined) && ~obj.indexOf(val);
      }
      this.assert(
          expected
        , 'expected #{this} to include ' + _.inspect(val)
        , 'expected #{this} to not include ' + _.inspect(val));
    }
  
    Assertion.addChainableMethod('include', include, includeChainingBehavior);
    Assertion.addChainableMethod('contain', include, includeChainingBehavior);
    Assertion.addChainableMethod('contains', include, includeChainingBehavior);
    Assertion.addChainableMethod('includes', include, includeChainingBehavior);
  
    /**
     * ### .ok
     *
     * Asserts that the target is truthy.
     *
     *     expect('everything').to.be.ok;
     *     expect(1).to.be.ok;
     *     expect(false).to.not.be.ok;
     *     expect(undefined).to.not.be.ok;
     *     expect(null).to.not.be.ok;
     *
     * @name ok
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('ok', function () {
      this.assert(
          flag(this, 'object')
        , 'expected #{this} to be truthy'
        , 'expected #{this} to be falsy');
    });
  
    /**
     * ### .true
     *
     * Asserts that the target is `true`.
     *
     *     expect(true).to.be.true;
     *     expect(1).to.not.be.true;
     *
     * @name true
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('true', function () {
      this.assert(
          true === flag(this, 'object')
        , 'expected #{this} to be true'
        , 'expected #{this} to be false'
        , this.negate ? false : true
      );
    });
  
    /**
     * ### .false
     *
     * Asserts that the target is `false`.
     *
     *     expect(false).to.be.false;
     *     expect(0).to.not.be.false;
     *
     * @name false
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('false', function () {
      this.assert(
          false === flag(this, 'object')
        , 'expected #{this} to be false'
        , 'expected #{this} to be true'
        , this.negate ? true : false
      );
    });
  
    /**
     * ### .null
     *
     * Asserts that the target is `null`.
     *
     *     expect(null).to.be.null;
     *     expect(undefined).to.not.be.null;
     *
     * @name null
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('null', function () {
      this.assert(
          null === flag(this, 'object')
        , 'expected #{this} to be null'
        , 'expected #{this} not to be null'
      );
    });
  
    /**
     * ### .undefined
     *
     * Asserts that the target is `undefined`.
     *
     *     expect(undefined).to.be.undefined;
     *     expect(null).to.not.be.undefined;
     *
     * @name undefined
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('undefined', function () {
      this.assert(
          undefined === flag(this, 'object')
        , 'expected #{this} to be undefined'
        , 'expected #{this} not to be undefined'
      );
    });
  
    /**
     * ### .NaN
     * Asserts that the target is `NaN`.
     *
     *     expect('foo').to.be.NaN;
     *     expect(4).not.to.be.NaN;
     *
     * @name NaN
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('NaN', function () {
      this.assert(
          isNaN(flag(this, 'object'))
          , 'expected #{this} to be NaN'
          , 'expected #{this} not to be NaN'
      );
    });
  
    /**
     * ### .exist
     *
     * Asserts that the target is neither `null` nor `undefined`.
     *
     *     var foo = 'hi'
     *       , bar = null
     *       , baz;
     *
     *     expect(foo).to.exist;
     *     expect(bar).to.not.exist;
     *     expect(baz).to.not.exist;
     *
     * @name exist
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('exist', function () {
      this.assert(
          null != flag(this, 'object')
        , 'expected #{this} to exist'
        , 'expected #{this} to not exist'
      );
    });
  
  
    /**
     * ### .empty
     *
     * Asserts that the target's length is `0`. For arrays and strings, it checks
     * the `length` property. For objects, it gets the count of
     * enumerable keys.
     *
     *     expect([]).to.be.empty;
     *     expect('').to.be.empty;
     *     expect({}).to.be.empty;
     *
     * @name empty
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('empty', function () {
      var obj = flag(this, 'object')
        , expected = obj;
  
      if (Array.isArray(obj) || 'string' === typeof object) {
        expected = obj.length;
      } else if (typeof obj === 'object') {
        expected = Object.keys(obj).length;
      }
  
      this.assert(
          !expected
        , 'expected #{this} to be empty'
        , 'expected #{this} not to be empty'
      );
    });
  
    /**
     * ### .arguments
     *
     * Asserts that the target is an arguments object.
     *
     *     function test () {
     *       expect(arguments).to.be.arguments;
     *     }
     *
     * @name arguments
     * @alias Arguments
     * @namespace BDD
     * @api public
     */
  
    function checkArguments () {
      var obj = flag(this, 'object')
        , type = Object.prototype.toString.call(obj);
      this.assert(
          '[object Arguments]' === type
        , 'expected #{this} to be arguments but got ' + type
        , 'expected #{this} to not be arguments'
      );
    }
  
    Assertion.addProperty('arguments', checkArguments);
    Assertion.addProperty('Arguments', checkArguments);
  
    /**
     * ### .equal(value)
     *
     * Asserts that the target is strictly equal (`===`) to `value`.
     * Alternately, if the `deep` flag is set, asserts that
     * the target is deeply equal to `value`.
     *
     *     expect('hello').to.equal('hello');
     *     expect(42).to.equal(42);
     *     expect(1).to.not.equal(true);
     *     expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
     *     expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
     *
     * @name equal
     * @alias equals
     * @alias eq
     * @alias deep.equal
     * @param {Mixed} value
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertEqual (val, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'deep')) {
        return this.eql(val);
      } else {
        this.assert(
            val === obj
          , 'expected #{this} to equal #{exp}'
          , 'expected #{this} to not equal #{exp}'
          , val
          , this._obj
          , true
        );
      }
    }
  
    Assertion.addMethod('equal', assertEqual);
    Assertion.addMethod('equals', assertEqual);
    Assertion.addMethod('eq', assertEqual);
  
    /**
     * ### .eql(value)
     *
     * Asserts that the target is deeply equal to `value`.
     *
     *     expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
     *     expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
     *
     * @name eql
     * @alias eqls
     * @param {Mixed} value
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertEql(obj, msg) {
      if (msg) flag(this, 'message', msg);
      this.assert(
          _.eql(obj, flag(this, 'object'))
        , 'expected #{this} to deeply equal #{exp}'
        , 'expected #{this} to not deeply equal #{exp}'
        , obj
        , this._obj
        , true
      );
    }
  
    Assertion.addMethod('eql', assertEql);
    Assertion.addMethod('eqls', assertEql);
  
    /**
     * ### .above(value)
     *
     * Asserts that the target is greater than `value`.
     *
     *     expect(10).to.be.above(5);
     *
     * Can also be used in conjunction with `length` to
     * assert a minimum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.above(2);
     *     expect([ 1, 2, 3 ]).to.have.length.above(2);
     *
     * @name above
     * @alias gt
     * @alias greaterThan
     * @param {Number} value
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertAbove (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len > n
          , 'expected #{this} to have a length above #{exp} but got #{act}'
          , 'expected #{this} to not have a length above #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj > n
          , 'expected #{this} to be above ' + n
          , 'expected #{this} to be at most ' + n
        );
      }
    }
  
    Assertion.addMethod('above', assertAbove);
    Assertion.addMethod('gt', assertAbove);
    Assertion.addMethod('greaterThan', assertAbove);
  
    /**
     * ### .least(value)
     *
     * Asserts that the target is greater than or equal to `value`.
     *
     *     expect(10).to.be.at.least(10);
     *
     * Can also be used in conjunction with `length` to
     * assert a minimum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.of.at.least(2);
     *     expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
     *
     * @name least
     * @alias gte
     * @param {Number} value
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertLeast (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len >= n
          , 'expected #{this} to have a length at least #{exp} but got #{act}'
          , 'expected #{this} to have a length below #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj >= n
          , 'expected #{this} to be at least ' + n
          , 'expected #{this} to be below ' + n
        );
      }
    }
  
    Assertion.addMethod('least', assertLeast);
    Assertion.addMethod('gte', assertLeast);
  
    /**
     * ### .below(value)
     *
     * Asserts that the target is less than `value`.
     *
     *     expect(5).to.be.below(10);
     *
     * Can also be used in conjunction with `length` to
     * assert a maximum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.below(4);
     *     expect([ 1, 2, 3 ]).to.have.length.below(4);
     *
     * @name below
     * @alias lt
     * @alias lessThan
     * @param {Number} value
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertBelow (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len < n
          , 'expected #{this} to have a length below #{exp} but got #{act}'
          , 'expected #{this} to not have a length below #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj < n
          , 'expected #{this} to be below ' + n
          , 'expected #{this} to be at least ' + n
        );
      }
    }
  
    Assertion.addMethod('below', assertBelow);
    Assertion.addMethod('lt', assertBelow);
    Assertion.addMethod('lessThan', assertBelow);
  
    /**
     * ### .most(value)
     *
     * Asserts that the target is less than or equal to `value`.
     *
     *     expect(5).to.be.at.most(5);
     *
     * Can also be used in conjunction with `length` to
     * assert a maximum length. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.of.at.most(4);
     *     expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
     *
     * @name most
     * @alias lte
     * @param {Number} value
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertMost (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len <= n
          , 'expected #{this} to have a length at most #{exp} but got #{act}'
          , 'expected #{this} to have a length above #{exp}'
          , n
          , len
        );
      } else {
        this.assert(
            obj <= n
          , 'expected #{this} to be at most ' + n
          , 'expected #{this} to be above ' + n
        );
      }
    }
  
    Assertion.addMethod('most', assertMost);
    Assertion.addMethod('lte', assertMost);
  
    /**
     * ### .within(start, finish)
     *
     * Asserts that the target is within a range.
     *
     *     expect(7).to.be.within(5,10);
     *
     * Can also be used in conjunction with `length` to
     * assert a length range. The benefit being a
     * more informative error message than if the length
     * was supplied directly.
     *
     *     expect('foo').to.have.length.within(2,4);
     *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);
     *
     * @name within
     * @param {Number} start lowerbound inclusive
     * @param {Number} finish upperbound inclusive
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    Assertion.addMethod('within', function (start, finish, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object')
        , range = start + '..' + finish;
      if (flag(this, 'doLength')) {
        new Assertion(obj, msg).to.have.property('length');
        var len = obj.length;
        this.assert(
            len >= start && len <= finish
          , 'expected #{this} to have a length within ' + range
          , 'expected #{this} to not have a length within ' + range
        );
      } else {
        this.assert(
            obj >= start && obj <= finish
          , 'expected #{this} to be within ' + range
          , 'expected #{this} to not be within ' + range
        );
      }
    });
  
    /**
     * ### .instanceof(constructor)
     *
     * Asserts that the target is an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , Chai = new Tea('chai');
     *
     *     expect(Chai).to.be.an.instanceof(Tea);
     *     expect([ 1, 2, 3 ]).to.be.instanceof(Array);
     *
     * @name instanceof
     * @param {Constructor} constructor
     * @param {String} message _optional_
     * @alias instanceOf
     * @namespace BDD
     * @api public
     */
  
    function assertInstanceOf (constructor, msg) {
      if (msg) flag(this, 'message', msg);
      var name = _.getName(constructor);
      this.assert(
          flag(this, 'object') instanceof constructor
        , 'expected #{this} to be an instance of ' + name
        , 'expected #{this} to not be an instance of ' + name
      );
    };
  
    Assertion.addMethod('instanceof', assertInstanceOf);
    Assertion.addMethod('instanceOf', assertInstanceOf);
  
    /**
     * ### .property(name, [value])
     *
     * Asserts that the target has a property `name`, optionally asserting that
     * the value of that property is strictly equal to  `value`.
     * If the `deep` flag is set, you can use dot- and bracket-notation for deep
     * references into objects and arrays.
     *
     *     // simple referencing
     *     var obj = { foo: 'bar' };
     *     expect(obj).to.have.property('foo');
     *     expect(obj).to.have.property('foo', 'bar');
     *
     *     // deep referencing
     *     var deepObj = {
     *         green: { tea: 'matcha' }
     *       , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
     *     };
     *
     *     expect(deepObj).to.have.deep.property('green.tea', 'matcha');
     *     expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
     *     expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
     *
     * You can also use an array as the starting point of a `deep.property`
     * assertion, or traverse nested arrays.
     *
     *     var arr = [
     *         [ 'chai', 'matcha', 'konacha' ]
     *       , [ { tea: 'chai' }
     *         , { tea: 'matcha' }
     *         , { tea: 'konacha' } ]
     *     ];
     *
     *     expect(arr).to.have.deep.property('[0][1]', 'matcha');
     *     expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
     *
     * Furthermore, `property` changes the subject of the assertion
     * to be the value of that property from the original object. This
     * permits for further chainable assertions on that property.
     *
     *     expect(obj).to.have.property('foo')
     *       .that.is.a('string');
     *     expect(deepObj).to.have.property('green')
     *       .that.is.an('object')
     *       .that.deep.equals({ tea: 'matcha' });
     *     expect(deepObj).to.have.property('teas')
     *       .that.is.an('array')
     *       .with.deep.property('[2]')
     *         .that.deep.equals({ tea: 'konacha' });
     *
     * Note that dots and bracket in `name` must be backslash-escaped when
     * the `deep` flag is set, while they must NOT be escaped when the `deep`
     * flag is not set.
     *
     *     // simple referencing
     *     var css = { '.link[target]': 42 };
     *     expect(css).to.have.property('.link[target]', 42);
     *
     *     // deep referencing
     *     var deepCss = { '.link': { '[target]': 42 }};
     *     expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
     *
     * @name property
     * @alias deep.property
     * @param {String} name
     * @param {Mixed} value (optional)
     * @param {String} message _optional_
     * @returns value of property for chaining
     * @namespace BDD
     * @api public
     */
  
    Assertion.addMethod('property', function (name, val, msg) {
      if (msg) flag(this, 'message', msg);
  
      var isDeep = !!flag(this, 'deep')
        , descriptor = isDeep ? 'deep property ' : 'property '
        , negate = flag(this, 'negate')
        , obj = flag(this, 'object')
        , pathInfo = isDeep ? _.getPathInfo(name, obj) : null
        , hasProperty = isDeep
          ? pathInfo.exists
          : _.hasProperty(name, obj)
        , value = isDeep
          ? pathInfo.value
          : obj[name];
  
      if (negate && arguments.length > 1) {
        if (undefined === value) {
          msg = (msg != null) ? msg + ': ' : '';
          throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
        }
      } else {
        this.assert(
            hasProperty
          , 'expected #{this} to have a ' + descriptor + _.inspect(name)
          , 'expected #{this} to not have ' + descriptor + _.inspect(name));
      }
  
      if (arguments.length > 1) {
        this.assert(
            val === value
          , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
          , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
          , val
          , value
        );
      }
  
      flag(this, 'object', value);
    });
  
  
    /**
     * ### .ownProperty(name)
     *
     * Asserts that the target has an own property `name`.
     *
     *     expect('test').to.have.ownProperty('length');
     *
     * @name ownProperty
     * @alias haveOwnProperty
     * @param {String} name
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertOwnProperty (name, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      this.assert(
          obj.hasOwnProperty(name)
        , 'expected #{this} to have own property ' + _.inspect(name)
        , 'expected #{this} to not have own property ' + _.inspect(name)
      );
    }
  
    Assertion.addMethod('ownProperty', assertOwnProperty);
    Assertion.addMethod('haveOwnProperty', assertOwnProperty);
  
    /**
     * ### .ownPropertyDescriptor(name[, descriptor[, message]])
     *
     * Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`.
     *
     *     expect('test').to.have.ownPropertyDescriptor('length');
     *     expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 });
     *     expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 });
     *     expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false);
     *     expect('test').ownPropertyDescriptor('length').to.have.keys('value');
     *
     * @name ownPropertyDescriptor
     * @alias haveOwnPropertyDescriptor
     * @param {String} name
     * @param {Object} descriptor _optional_
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertOwnPropertyDescriptor (name, descriptor, msg) {
      if (typeof descriptor === 'string') {
        msg = descriptor;
        descriptor = null;
      }
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
      if (actualDescriptor && descriptor) {
        this.assert(
            _.eql(descriptor, actualDescriptor)
          , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)
          , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)
          , descriptor
          , actualDescriptor
          , true
        );
      } else {
        this.assert(
            actualDescriptor
          , 'expected #{this} to have an own property descriptor for ' + _.inspect(name)
          , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name)
        );
      }
      flag(this, 'object', actualDescriptor);
    }
  
    Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
    Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
  
    /**
     * ### .length
     *
     * Sets the `doLength` flag later used as a chain precursor to a value
     * comparison for the `length` property.
     *
     *     expect('foo').to.have.length.above(2);
     *     expect([ 1, 2, 3 ]).to.have.length.above(2);
     *     expect('foo').to.have.length.below(4);
     *     expect([ 1, 2, 3 ]).to.have.length.below(4);
     *     expect('foo').to.have.length.within(2,4);
     *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);
     *
     * *Deprecation notice:* Using `length` as an assertion will be deprecated
     * in version 2.4.0 and removed in 3.0.0. Code using the old style of
     * asserting for `length` property value using `length(value)` should be
     * switched to use `lengthOf(value)` instead.
     *
     * @name length
     * @namespace BDD
     * @api public
     */
  
    /**
     * ### .lengthOf(value[, message])
     *
     * Asserts that the target's `length` property has
     * the expected value.
     *
     *     expect([ 1, 2, 3]).to.have.lengthOf(3);
     *     expect('foobar').to.have.lengthOf(6);
     *
     * @name lengthOf
     * @param {Number} length
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertLengthChain () {
      flag(this, 'doLength', true);
    }
  
    function assertLength (n, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).to.have.property('length');
      var len = obj.length;
  
      this.assert(
          len == n
        , 'expected #{this} to have a length of #{exp} but got #{act}'
        , 'expected #{this} to not have a length of #{act}'
        , n
        , len
      );
    }
  
    Assertion.addChainableMethod('length', assertLength, assertLengthChain);
    Assertion.addMethod('lengthOf', assertLength);
  
    /**
     * ### .match(regexp)
     *
     * Asserts that the target matches a regular expression.
     *
     *     expect('foobar').to.match(/^foo/);
     *
     * @name match
     * @alias matches
     * @param {RegExp} RegularExpression
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
    function assertMatch(re, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      this.assert(
          re.exec(obj)
        , 'expected #{this} to match ' + re
        , 'expected #{this} not to match ' + re
      );
    }
  
    Assertion.addMethod('match', assertMatch);
    Assertion.addMethod('matches', assertMatch);
  
    /**
     * ### .string(string)
     *
     * Asserts that the string target contains another string.
     *
     *     expect('foobar').to.have.string('bar');
     *
     * @name string
     * @param {String} string
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    Assertion.addMethod('string', function (str, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).is.a('string');
  
      this.assert(
          ~obj.indexOf(str)
        , 'expected #{this} to contain ' + _.inspect(str)
        , 'expected #{this} to not contain ' + _.inspect(str)
      );
    });
  
  
    /**
     * ### .keys(key1, [key2], [...])
     *
     * Asserts that the target contains any or all of the passed-in keys.
     * Use in combination with `any`, `all`, `contains`, or `have` will affect
     * what will pass.
     *
     * When used in conjunction with `any`, at least one key that is passed
     * in must exist in the target object. This is regardless whether or not
     * the `have` or `contain` qualifiers are used. Note, either `any` or `all`
     * should be used in the assertion. If neither are used, the assertion is
     * defaulted to `all`.
     *
     * When both `all` and `contain` are used, the target object must have at
     * least all of the passed-in keys but may have more keys not listed.
     *
     * When both `all` and `have` are used, the target object must both contain
     * all of the passed-in keys AND the number of keys in the target object must
     * match the number of keys passed in (in other words, a target object must
     * have all and only all of the passed-in keys).
     *
     *     expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz');
     *     expect({ foo: 1, bar: 2 }).to.have.any.keys('foo');
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz');
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']);
     *     expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6});
     *     expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']);
     *     expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7});
     *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']);
     *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys({'bar': 6});
     *
     *
     * @name keys
     * @alias key
     * @param {...String|Array|Object} keys
     * @namespace BDD
     * @api public
     */
  
    function assertKeys (keys) {
      var obj = flag(this, 'object')
        , str
        , ok = true
        , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments';
  
      switch (_.type(keys)) {
        case "array":
          if (arguments.length > 1) throw (new Error(mixedArgsMsg));
          break;
        case "object":
          if (arguments.length > 1) throw (new Error(mixedArgsMsg));
          keys = Object.keys(keys);
          break;
        default:
          keys = Array.prototype.slice.call(arguments);
      }
  
      if (!keys.length) throw new Error('keys required');
  
      var actual = Object.keys(obj)
        , expected = keys
        , len = keys.length
        , any = flag(this, 'any')
        , all = flag(this, 'all');
  
      if (!any && !all) {
        all = true;
      }
  
      // Has any
      if (any) {
        var intersection = expected.filter(function(key) {
          return ~actual.indexOf(key);
        });
        ok = intersection.length > 0;
      }
  
      // Has all
      if (all) {
        ok = keys.every(function(key){
          return ~actual.indexOf(key);
        });
        if (!flag(this, 'negate') && !flag(this, 'contains')) {
          ok = ok && keys.length == actual.length;
        }
      }
  
      // Key string
      if (len > 1) {
        keys = keys.map(function(key){
          return _.inspect(key);
        });
        var last = keys.pop();
        if (all) {
          str = keys.join(', ') + ', and ' + last;
        }
        if (any) {
          str = keys.join(', ') + ', or ' + last;
        }
      } else {
        str = _.inspect(keys[0]);
      }
  
      // Form
      str = (len > 1 ? 'keys ' : 'key ') + str;
  
      // Have / include
      str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
  
      // Assertion
      this.assert(
          ok
        , 'expected #{this} to ' + str
        , 'expected #{this} to not ' + str
        , expected.slice(0).sort()
        , actual.sort()
        , true
      );
    }
  
    Assertion.addMethod('keys', assertKeys);
    Assertion.addMethod('key', assertKeys);
  
    /**
     * ### .throw(constructor)
     *
     * Asserts that the function target will throw a specific error, or specific type of error
     * (as determined using `instanceof`), optionally with a RegExp or string inclusion test
     * for the error's message.
     *
     *     var err = new ReferenceError('This is a bad function.');
     *     var fn = function () { throw err; }
     *     expect(fn).to.throw(ReferenceError);
     *     expect(fn).to.throw(Error);
     *     expect(fn).to.throw(/bad function/);
     *     expect(fn).to.not.throw('good function');
     *     expect(fn).to.throw(ReferenceError, /bad function/);
     *     expect(fn).to.throw(err);
     *
     * Please note that when a throw expectation is negated, it will check each
     * parameter independently, starting with error constructor type. The appropriate way
     * to check for the existence of a type of error but for a message that does not match
     * is to use `and`.
     *
     *     expect(fn).to.throw(ReferenceError)
     *        .and.not.throw(/good function/);
     *
     * @name throw
     * @alias throws
     * @alias Throw
     * @param {ErrorConstructor} constructor
     * @param {String|RegExp} expected error message
     * @param {String} message _optional_
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @returns error for chaining (null if no error)
     * @namespace BDD
     * @api public
     */
  
    function assertThrows (constructor, errMsg, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      new Assertion(obj, msg).is.a('function');
  
      var thrown = false
        , desiredError = null
        , name = null
        , thrownError = null;
  
      if (arguments.length === 0) {
        errMsg = null;
        constructor = null;
      } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
        errMsg = constructor;
        constructor = null;
      } else if (constructor && constructor instanceof Error) {
        desiredError = constructor;
        constructor = null;
        errMsg = null;
      } else if (typeof constructor === 'function') {
        name = constructor.prototype.name;
        if (!name || (name === 'Error' && constructor !== Error)) {
          name = constructor.name || (new constructor()).name;
        }
      } else {
        constructor = null;
      }
  
      try {
        obj();
      } catch (err) {
        // first, check desired error
        if (desiredError) {
          this.assert(
              err === desiredError
            , 'expected #{this} to throw #{exp} but #{act} was thrown'
            , 'expected #{this} to not throw #{exp}'
            , (desiredError instanceof Error ? desiredError.toString() : desiredError)
            , (err instanceof Error ? err.toString() : err)
          );
  
          flag(this, 'object', err);
          return this;
        }
  
        // next, check constructor
        if (constructor) {
          this.assert(
              err instanceof constructor
            , 'expected #{this} to throw #{exp} but #{act} was thrown'
            , 'expected #{this} to not throw #{exp} but #{act} was thrown'
            , name
            , (err instanceof Error ? err.toString() : err)
          );
  
          if (!errMsg) {
            flag(this, 'object', err);
            return this;
          }
        }
  
        // next, check message
        var message = 'error' === _.type(err) && "message" in err
          ? err.message
          : '' + err;
  
        if ((message != null) && errMsg && errMsg instanceof RegExp) {
          this.assert(
              errMsg.exec(message)
            , 'expected #{this} to throw error matching #{exp} but got #{act}'
            , 'expected #{this} to throw error not matching #{exp}'
            , errMsg
            , message
          );
  
          flag(this, 'object', err);
          return this;
        } else if ((message != null) && errMsg && 'string' === typeof errMsg) {
          this.assert(
              ~message.indexOf(errMsg)
            , 'expected #{this} to throw error including #{exp} but got #{act}'
            , 'expected #{this} to throw error not including #{act}'
            , errMsg
            , message
          );
  
          flag(this, 'object', err);
          return this;
        } else {
          thrown = true;
          thrownError = err;
        }
      }
  
      var actuallyGot = ''
        , expectedThrown = name !== null
          ? name
          : desiredError
            ? '#{exp}' //_.inspect(desiredError)
            : 'an error';
  
      if (thrown) {
        actuallyGot = ' but #{act} was thrown'
      }
  
      this.assert(
          thrown === true
        , 'expected #{this} to throw ' + expectedThrown + actuallyGot
        , 'expected #{this} to not throw ' + expectedThrown + actuallyGot
        , (desiredError instanceof Error ? desiredError.toString() : desiredError)
        , (thrownError instanceof Error ? thrownError.toString() : thrownError)
      );
  
      flag(this, 'object', thrownError);
    };
  
    Assertion.addMethod('throw', assertThrows);
    Assertion.addMethod('throws', assertThrows);
    Assertion.addMethod('Throw', assertThrows);
  
    /**
     * ### .respondTo(method)
     *
     * Asserts that the object or class target will respond to a method.
     *
     *     Klass.prototype.bar = function(){};
     *     expect(Klass).to.respondTo('bar');
     *     expect(obj).to.respondTo('bar');
     *
     * To check if a constructor will respond to a static function,
     * set the `itself` flag.
     *
     *     Klass.baz = function(){};
     *     expect(Klass).itself.to.respondTo('baz');
     *
     * @name respondTo
     * @alias respondsTo
     * @param {String} method
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function respondTo (method, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object')
        , itself = flag(this, 'itself')
        , context = ('function' === _.type(obj) && !itself)
          ? obj.prototype[method]
          : obj[method];
  
      this.assert(
          'function' === typeof context
        , 'expected #{this} to respond to ' + _.inspect(method)
        , 'expected #{this} to not respond to ' + _.inspect(method)
      );
    }
  
    Assertion.addMethod('respondTo', respondTo);
    Assertion.addMethod('respondsTo', respondTo);
  
    /**
     * ### .itself
     *
     * Sets the `itself` flag, later used by the `respondTo` assertion.
     *
     *     function Foo() {}
     *     Foo.bar = function() {}
     *     Foo.prototype.baz = function() {}
     *
     *     expect(Foo).itself.to.respondTo('bar');
     *     expect(Foo).itself.not.to.respondTo('baz');
     *
     * @name itself
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('itself', function () {
      flag(this, 'itself', true);
    });
  
    /**
     * ### .satisfy(method)
     *
     * Asserts that the target passes a given truth test.
     *
     *     expect(1).to.satisfy(function(num) { return num > 0; });
     *
     * @name satisfy
     * @alias satisfies
     * @param {Function} matcher
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function satisfy (matcher, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
      var result = matcher(obj);
      this.assert(
          result
        , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
        , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
        , this.negate ? false : true
        , result
      );
    }
  
    Assertion.addMethod('satisfy', satisfy);
    Assertion.addMethod('satisfies', satisfy);
  
    /**
     * ### .closeTo(expected, delta)
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     expect(1.5).to.be.closeTo(1, 0.5);
     *
     * @name closeTo
     * @alias approximately
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function closeTo(expected, delta, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
  
      new Assertion(obj, msg).is.a('number');
      if (_.type(expected) !== 'number' || _.type(delta) !== 'number') {
        throw new Error('the arguments to closeTo or approximately must be numbers');
      }
  
      this.assert(
          Math.abs(obj - expected) <= delta
        , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
        , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
      );
    }
  
    Assertion.addMethod('closeTo', closeTo);
    Assertion.addMethod('approximately', closeTo);
  
    function isSubsetOf(subset, superset, cmp) {
      return subset.every(function(elem) {
        if (!cmp) return superset.indexOf(elem) !== -1;
  
        return superset.some(function(elem2) {
          return cmp(elem, elem2);
        });
      })
    }
  
    /**
     * ### .members(set)
     *
     * Asserts that the target is a superset of `set`,
     * or that the target and `set` have the same strictly-equal (===) members.
     * Alternately, if the `deep` flag is set, set members are compared for deep
     * equality.
     *
     *     expect([1, 2, 3]).to.include.members([3, 2]);
     *     expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
     *
     *     expect([4, 2]).to.have.members([2, 4]);
     *     expect([5, 2]).to.not.have.members([5, 2, 1]);
     *
     *     expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
     *
     * @name members
     * @param {Array} set
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    Assertion.addMethod('members', function (subset, msg) {
      if (msg) flag(this, 'message', msg);
      var obj = flag(this, 'object');
  
      new Assertion(obj).to.be.an('array');
      new Assertion(subset).to.be.an('array');
  
      var cmp = flag(this, 'deep') ? _.eql : undefined;
  
      if (flag(this, 'contains')) {
        return this.assert(
            isSubsetOf(subset, obj, cmp)
          , 'expected #{this} to be a superset of #{act}'
          , 'expected #{this} to not be a superset of #{act}'
          , obj
          , subset
        );
      }
  
      this.assert(
          isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
          , 'expected #{this} to have the same members as #{act}'
          , 'expected #{this} to not have the same members as #{act}'
          , obj
          , subset
      );
    });
  
    /**
     * ### .oneOf(list)
     *
     * Assert that a value appears somewhere in the top level of array `list`.
     *
     *     expect('a').to.be.oneOf(['a', 'b', 'c']);
     *     expect(9).to.not.be.oneOf(['z']);
     *     expect([3]).to.not.be.oneOf([1, 2, [3]]);
     *
     *     var three = [3];
     *     // for object-types, contents are not compared
     *     expect(three).to.not.be.oneOf([1, 2, [3]]);
     *     // comparing references works
     *     expect(three).to.be.oneOf([1, 2, three]);
     *
     * @name oneOf
     * @param {Array<*>} list
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function oneOf (list, msg) {
      if (msg) flag(this, 'message', msg);
      var expected = flag(this, 'object');
      new Assertion(list).to.be.an('array');
  
      this.assert(
          list.indexOf(expected) > -1
        , 'expected #{this} to be one of #{exp}'
        , 'expected #{this} to not be one of #{exp}'
        , list
        , expected
      );
    }
  
    Assertion.addMethod('oneOf', oneOf);
  
  
    /**
     * ### .change(function)
     *
     * Asserts that a function changes an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val += 3 };
     *     var noChangeFn = function() { return 'foo' + 'bar'; }
     *     expect(fn).to.change(obj, 'val');
     *     expect(noChangeFn).to.not.change(obj, 'val')
     *
     * @name change
     * @alias changes
     * @alias Change
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertChanges (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        initial !== object[prop]
        , 'expected .' + prop + ' to change'
        , 'expected .' + prop + ' to not change'
      );
    }
  
    Assertion.addChainableMethod('change', assertChanges);
    Assertion.addChainableMethod('changes', assertChanges);
  
    /**
     * ### .increase(function)
     *
     * Asserts that a function increases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 15 };
     *     expect(fn).to.increase(obj, 'val');
     *
     * @name increase
     * @alias increases
     * @alias Increase
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertIncreases (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        object[prop] - initial > 0
        , 'expected .' + prop + ' to increase'
        , 'expected .' + prop + ' to not increase'
      );
    }
  
    Assertion.addChainableMethod('increase', assertIncreases);
    Assertion.addChainableMethod('increases', assertIncreases);
  
    /**
     * ### .decrease(function)
     *
     * Asserts that a function decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 5 };
     *     expect(fn).to.decrease(obj, 'val');
     *
     * @name decrease
     * @alias decreases
     * @alias Decrease
     * @param {String} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace BDD
     * @api public
     */
  
    function assertDecreases (object, prop, msg) {
      if (msg) flag(this, 'message', msg);
      var fn = flag(this, 'object');
      new Assertion(object, msg).to.have.property(prop);
      new Assertion(fn).is.a('function');
  
      var initial = object[prop];
      fn();
  
      this.assert(
        object[prop] - initial < 0
        , 'expected .' + prop + ' to decrease'
        , 'expected .' + prop + ' to not decrease'
      );
    }
  
    Assertion.addChainableMethod('decrease', assertDecreases);
    Assertion.addChainableMethod('decreases', assertDecreases);
  
    /**
     * ### .extensible
     *
     * Asserts that the target is extensible (can have new properties added to
     * it).
     *
     *     var nonExtensibleObject = Object.preventExtensions({});
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freeze({});
     *
     *     expect({}).to.be.extensible;
     *     expect(nonExtensibleObject).to.not.be.extensible;
     *     expect(sealedObject).to.not.be.extensible;
     *     expect(frozenObject).to.not.be.extensible;
     *
     * @name extensible
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('extensible', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false.
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isExtensible;
  
      try {
        isExtensible = Object.isExtensible(obj);
      } catch (err) {
        if (err instanceof TypeError) isExtensible = false;
        else throw err;
      }
  
      this.assert(
        isExtensible
        , 'expected #{this} to be extensible'
        , 'expected #{this} to not be extensible'
      );
    });
  
    /**
     * ### .sealed
     *
     * Asserts that the target is sealed (cannot have new properties added to it
     * and its existing properties cannot be removed).
     *
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freeze({});
     *
     *     expect(sealedObject).to.be.sealed;
     *     expect(frozenObject).to.be.sealed;
     *     expect({}).to.not.be.sealed;
     *
     * @name sealed
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('sealed', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true.
      // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isSealed;
  
      try {
        isSealed = Object.isSealed(obj);
      } catch (err) {
        if (err instanceof TypeError) isSealed = true;
        else throw err;
      }
  
      this.assert(
        isSealed
        , 'expected #{this} to be sealed'
        , 'expected #{this} to not be sealed'
      );
    });
  
    /**
     * ### .frozen
     *
     * Asserts that the target is frozen (cannot have new properties added to it
     * and its existing properties cannot be modified).
     *
     *     var frozenObject = Object.freeze({});
     *
     *     expect(frozenObject).to.be.frozen;
     *     expect({}).to.not.be.frozen;
     *
     * @name frozen
     * @namespace BDD
     * @api public
     */
  
    Assertion.addProperty('frozen', function() {
      var obj = flag(this, 'object');
  
      // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
      // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true.
      // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen
      // The following provides ES6 behavior when a TypeError is thrown under ES5.
  
      var isFrozen;
  
      try {
        isFrozen = Object.isFrozen(obj);
      } catch (err) {
        if (err instanceof TypeError) isFrozen = true;
        else throw err;
      }
  
      this.assert(
        isFrozen
        , 'expected #{this} to be frozen'
        , 'expected #{this} to not be frozen'
      );
    });
  };
  
  },{}],218:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  
  module.exports = function (chai, util) {
  
    /*!
     * Chai dependencies.
     */
  
    var Assertion = chai.Assertion
      , flag = util.flag;
  
    /*!
     * Module export.
     */
  
    /**
     * ### assert(expression, message)
     *
     * Write your own test expressions.
     *
     *     assert('foo' !== 'bar', 'foo is not bar');
     *     assert(Array.isArray([]), 'empty arrays are arrays');
     *
     * @param {Mixed} expression to test for truthiness
     * @param {String} message to display on error
     * @name assert
     * @namespace Assert
     * @api public
     */
  
    var assert = chai.assert = function (express, errmsg) {
      var test = new Assertion(null, null, chai.assert);
      test.assert(
          express
        , errmsg
        , '[ negation message unavailable ]'
      );
    };
  
    /**
     * ### .fail(actual, expected, [message], [operator])
     *
     * Throw a failure. Node.js `assert` module-compatible.
     *
     * @name fail
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @param {String} operator
     * @namespace Assert
     * @api public
     */
  
    assert.fail = function (actual, expected, message, operator) {
      message = message || 'assert.fail()';
      throw new chai.AssertionError(message, {
          actual: actual
        , expected: expected
        , operator: operator
      }, assert.fail);
    };
  
    /**
     * ### .isOk(object, [message])
     *
     * Asserts that `object` is truthy.
     *
     *     assert.isOk('everything', 'everything is ok');
     *     assert.isOk(false, 'this will fail');
     *
     * @name isOk
     * @alias ok
     * @param {Mixed} object to test
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isOk = function (val, msg) {
      new Assertion(val, msg).is.ok;
    };
  
    /**
     * ### .isNotOk(object, [message])
     *
     * Asserts that `object` is falsy.
     *
     *     assert.isNotOk('everything', 'this will fail');
     *     assert.isNotOk(false, 'this will pass');
     *
     * @name isNotOk
     * @alias notOk
     * @param {Mixed} object to test
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotOk = function (val, msg) {
      new Assertion(val, msg).is.not.ok;
    };
  
    /**
     * ### .equal(actual, expected, [message])
     *
     * Asserts non-strict equality (`==`) of `actual` and `expected`.
     *
     *     assert.equal(3, '3', '== coerces values to strings');
     *
     * @name equal
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.equal = function (act, exp, msg) {
      var test = new Assertion(act, msg, assert.equal);
  
      test.assert(
          exp == flag(test, 'object')
        , 'expected #{this} to equal #{exp}'
        , 'expected #{this} to not equal #{act}'
        , exp
        , act
      );
    };
  
    /**
     * ### .notEqual(actual, expected, [message])
     *
     * Asserts non-strict inequality (`!=`) of `actual` and `expected`.
     *
     *     assert.notEqual(3, 4, 'these numbers are not equal');
     *
     * @name notEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notEqual = function (act, exp, msg) {
      var test = new Assertion(act, msg, assert.notEqual);
  
      test.assert(
          exp != flag(test, 'object')
        , 'expected #{this} to not equal #{exp}'
        , 'expected #{this} to equal #{act}'
        , exp
        , act
      );
    };
  
    /**
     * ### .strictEqual(actual, expected, [message])
     *
     * Asserts strict equality (`===`) of `actual` and `expected`.
     *
     *     assert.strictEqual(true, true, 'these booleans are strictly equal');
     *
     * @name strictEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.strictEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.equal(exp);
    };
  
    /**
     * ### .notStrictEqual(actual, expected, [message])
     *
     * Asserts strict inequality (`!==`) of `actual` and `expected`.
     *
     *     assert.notStrictEqual(3, '3', 'no coercion for strict equality');
     *
     * @name notStrictEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notStrictEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.not.equal(exp);
    };
  
    /**
     * ### .deepEqual(actual, expected, [message])
     *
     * Asserts that `actual` is deeply equal to `expected`.
     *
     *     assert.deepEqual({ tea: 'green' }, { tea: 'green' });
     *
     * @name deepEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.deepEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.eql(exp);
    };
  
    /**
     * ### .notDeepEqual(actual, expected, [message])
     *
     * Assert that `actual` is not deeply equal to `expected`.
     *
     *     assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
     *
     * @name notDeepEqual
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notDeepEqual = function (act, exp, msg) {
      new Assertion(act, msg).to.not.eql(exp);
    };
  
     /**
     * ### .isAbove(valueToCheck, valueToBeAbove, [message])
     *
     * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`
     *
     *     assert.isAbove(5, 2, '5 is strictly greater than 2');
     *
     * @name isAbove
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAbove
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isAbove = function (val, abv, msg) {
      new Assertion(val, msg).to.be.above(abv);
    };
  
     /**
     * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message])
     *
     * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast`
     *
     *     assert.isAtLeast(5, 2, '5 is greater or equal to 2');
     *     assert.isAtLeast(3, 3, '3 is greater or equal to 3');
     *
     * @name isAtLeast
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAtLeast
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isAtLeast = function (val, atlst, msg) {
      new Assertion(val, msg).to.be.least(atlst);
    };
  
     /**
     * ### .isBelow(valueToCheck, valueToBeBelow, [message])
     *
     * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`
     *
     *     assert.isBelow(3, 6, '3 is strictly less than 6');
     *
     * @name isBelow
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeBelow
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isBelow = function (val, blw, msg) {
      new Assertion(val, msg).to.be.below(blw);
    };
  
     /**
     * ### .isAtMost(valueToCheck, valueToBeAtMost, [message])
     *
     * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost`
     *
     *     assert.isAtMost(3, 6, '3 is less than or equal to 6');
     *     assert.isAtMost(4, 4, '4 is less than or equal to 4');
     *
     * @name isAtMost
     * @param {Mixed} valueToCheck
     * @param {Mixed} valueToBeAtMost
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isAtMost = function (val, atmst, msg) {
      new Assertion(val, msg).to.be.most(atmst);
    };
  
    /**
     * ### .isTrue(value, [message])
     *
     * Asserts that `value` is true.
     *
     *     var teaServed = true;
     *     assert.isTrue(teaServed, 'the tea has been served');
     *
     * @name isTrue
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isTrue = function (val, msg) {
      new Assertion(val, msg).is['true'];
    };
  
    /**
     * ### .isNotTrue(value, [message])
     *
     * Asserts that `value` is not true.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotTrue(tea, 'great, time for tea!');
     *
     * @name isNotTrue
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotTrue = function (val, msg) {
      new Assertion(val, msg).to.not.equal(true);
    };
  
    /**
     * ### .isFalse(value, [message])
     *
     * Asserts that `value` is false.
     *
     *     var teaServed = false;
     *     assert.isFalse(teaServed, 'no tea yet? hmm...');
     *
     * @name isFalse
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isFalse = function (val, msg) {
      new Assertion(val, msg).is['false'];
    };
  
    /**
     * ### .isNotFalse(value, [message])
     *
     * Asserts that `value` is not false.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotFalse(tea, 'great, time for tea!');
     *
     * @name isNotFalse
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotFalse = function (val, msg) {
      new Assertion(val, msg).to.not.equal(false);
    };
  
    /**
     * ### .isNull(value, [message])
     *
     * Asserts that `value` is null.
     *
     *     assert.isNull(err, 'there was no error');
     *
     * @name isNull
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNull = function (val, msg) {
      new Assertion(val, msg).to.equal(null);
    };
  
    /**
     * ### .isNotNull(value, [message])
     *
     * Asserts that `value` is not null.
     *
     *     var tea = 'tasty chai';
     *     assert.isNotNull(tea, 'great, time for tea!');
     *
     * @name isNotNull
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotNull = function (val, msg) {
      new Assertion(val, msg).to.not.equal(null);
    };
  
    /**
     * ### .isNaN
     * Asserts that value is NaN
     *
     *    assert.isNaN('foo', 'foo is NaN');
     *
     * @name isNaN
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNaN = function (val, msg) {
      new Assertion(val, msg).to.be.NaN;
    };
  
    /**
     * ### .isNotNaN
     * Asserts that value is not NaN
     *
     *    assert.isNotNaN(4, '4 is not NaN');
     *
     * @name isNotNaN
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
    assert.isNotNaN = function (val, msg) {
      new Assertion(val, msg).not.to.be.NaN;
    };
  
    /**
     * ### .isUndefined(value, [message])
     *
     * Asserts that `value` is `undefined`.
     *
     *     var tea;
     *     assert.isUndefined(tea, 'no tea defined');
     *
     * @name isUndefined
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isUndefined = function (val, msg) {
      new Assertion(val, msg).to.equal(undefined);
    };
  
    /**
     * ### .isDefined(value, [message])
     *
     * Asserts that `value` is not `undefined`.
     *
     *     var tea = 'cup of chai';
     *     assert.isDefined(tea, 'tea has been defined');
     *
     * @name isDefined
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isDefined = function (val, msg) {
      new Assertion(val, msg).to.not.equal(undefined);
    };
  
    /**
     * ### .isFunction(value, [message])
     *
     * Asserts that `value` is a function.
     *
     *     function serveTea() { return 'cup of tea'; };
     *     assert.isFunction(serveTea, 'great, we can have tea now');
     *
     * @name isFunction
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isFunction = function (val, msg) {
      new Assertion(val, msg).to.be.a('function');
    };
  
    /**
     * ### .isNotFunction(value, [message])
     *
     * Asserts that `value` is _not_ a function.
     *
     *     var serveTea = [ 'heat', 'pour', 'sip' ];
     *     assert.isNotFunction(serveTea, 'great, we have listed the steps');
     *
     * @name isNotFunction
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotFunction = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('function');
    };
  
    /**
     * ### .isObject(value, [message])
     *
     * Asserts that `value` is an object of type 'Object' (as revealed by `Object.prototype.toString`).
     * _The assertion does not match subclassed objects._
     *
     *     var selection = { name: 'Chai', serve: 'with spices' };
     *     assert.isObject(selection, 'tea selection is an object');
     *
     * @name isObject
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isObject = function (val, msg) {
      new Assertion(val, msg).to.be.a('object');
    };
  
    /**
     * ### .isNotObject(value, [message])
     *
     * Asserts that `value` is _not_ an object of type 'Object' (as revealed by `Object.prototype.toString`).
     *
     *     var selection = 'chai'
     *     assert.isNotObject(selection, 'tea selection is not an object');
     *     assert.isNotObject(null, 'null is not an object');
     *
     * @name isNotObject
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotObject = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('object');
    };
  
    /**
     * ### .isArray(value, [message])
     *
     * Asserts that `value` is an array.
     *
     *     var menu = [ 'green', 'chai', 'oolong' ];
     *     assert.isArray(menu, 'what kind of tea do we want?');
     *
     * @name isArray
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isArray = function (val, msg) {
      new Assertion(val, msg).to.be.an('array');
    };
  
    /**
     * ### .isNotArray(value, [message])
     *
     * Asserts that `value` is _not_ an array.
     *
     *     var menu = 'green|chai|oolong';
     *     assert.isNotArray(menu, 'what kind of tea do we want?');
     *
     * @name isNotArray
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotArray = function (val, msg) {
      new Assertion(val, msg).to.not.be.an('array');
    };
  
    /**
     * ### .isString(value, [message])
     *
     * Asserts that `value` is a string.
     *
     *     var teaOrder = 'chai';
     *     assert.isString(teaOrder, 'order placed');
     *
     * @name isString
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isString = function (val, msg) {
      new Assertion(val, msg).to.be.a('string');
    };
  
    /**
     * ### .isNotString(value, [message])
     *
     * Asserts that `value` is _not_ a string.
     *
     *     var teaOrder = 4;
     *     assert.isNotString(teaOrder, 'order placed');
     *
     * @name isNotString
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotString = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('string');
    };
  
    /**
     * ### .isNumber(value, [message])
     *
     * Asserts that `value` is a number.
     *
     *     var cups = 2;
     *     assert.isNumber(cups, 'how many cups');
     *
     * @name isNumber
     * @param {Number} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNumber = function (val, msg) {
      new Assertion(val, msg).to.be.a('number');
    };
  
    /**
     * ### .isNotNumber(value, [message])
     *
     * Asserts that `value` is _not_ a number.
     *
     *     var cups = '2 cups please';
     *     assert.isNotNumber(cups, 'how many cups');
     *
     * @name isNotNumber
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotNumber = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('number');
    };
  
    /**
     * ### .isBoolean(value, [message])
     *
     * Asserts that `value` is a boolean.
     *
     *     var teaReady = true
     *       , teaServed = false;
     *
     *     assert.isBoolean(teaReady, 'is the tea ready');
     *     assert.isBoolean(teaServed, 'has tea been served');
     *
     * @name isBoolean
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isBoolean = function (val, msg) {
      new Assertion(val, msg).to.be.a('boolean');
    };
  
    /**
     * ### .isNotBoolean(value, [message])
     *
     * Asserts that `value` is _not_ a boolean.
     *
     *     var teaReady = 'yep'
     *       , teaServed = 'nope';
     *
     *     assert.isNotBoolean(teaReady, 'is the tea ready');
     *     assert.isNotBoolean(teaServed, 'has tea been served');
     *
     * @name isNotBoolean
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.isNotBoolean = function (val, msg) {
      new Assertion(val, msg).to.not.be.a('boolean');
    };
  
    /**
     * ### .typeOf(value, name, [message])
     *
     * Asserts that `value`'s type is `name`, as determined by
     * `Object.prototype.toString`.
     *
     *     assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
     *     assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
     *     assert.typeOf('tea', 'string', 'we have a string');
     *     assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
     *     assert.typeOf(null, 'null', 'we have a null');
     *     assert.typeOf(undefined, 'undefined', 'we have an undefined');
     *
     * @name typeOf
     * @param {Mixed} value
     * @param {String} name
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.typeOf = function (val, type, msg) {
      new Assertion(val, msg).to.be.a(type);
    };
  
    /**
     * ### .notTypeOf(value, name, [message])
     *
     * Asserts that `value`'s type is _not_ `name`, as determined by
     * `Object.prototype.toString`.
     *
     *     assert.notTypeOf('tea', 'number', 'strings are not numbers');
     *
     * @name notTypeOf
     * @param {Mixed} value
     * @param {String} typeof name
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notTypeOf = function (val, type, msg) {
      new Assertion(val, msg).to.not.be.a(type);
    };
  
    /**
     * ### .instanceOf(object, constructor, [message])
     *
     * Asserts that `value` is an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , chai = new Tea('chai');
     *
     *     assert.instanceOf(chai, Tea, 'chai is an instance of tea');
     *
     * @name instanceOf
     * @param {Object} object
     * @param {Constructor} constructor
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.instanceOf = function (val, type, msg) {
      new Assertion(val, msg).to.be.instanceOf(type);
    };
  
    /**
     * ### .notInstanceOf(object, constructor, [message])
     *
     * Asserts `value` is not an instance of `constructor`.
     *
     *     var Tea = function (name) { this.name = name; }
     *       , chai = new String('chai');
     *
     *     assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
     *
     * @name notInstanceOf
     * @param {Object} object
     * @param {Constructor} constructor
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notInstanceOf = function (val, type, msg) {
      new Assertion(val, msg).to.not.be.instanceOf(type);
    };
  
    /**
     * ### .include(haystack, needle, [message])
     *
     * Asserts that `haystack` includes `needle`. Works
     * for strings and arrays.
     *
     *     assert.include('foobar', 'bar', 'foobar contains string "bar"');
     *     assert.include([ 1, 2, 3 ], 3, 'array contains value');
     *
     * @name include
     * @param {Array|String} haystack
     * @param {Mixed} needle
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.include = function (exp, inc, msg) {
      new Assertion(exp, msg, assert.include).include(inc);
    };
  
    /**
     * ### .notInclude(haystack, needle, [message])
     *
     * Asserts that `haystack` does not include `needle`. Works
     * for strings and arrays.
     *
     *     assert.notInclude('foobar', 'baz', 'string not include substring');
     *     assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
     *
     * @name notInclude
     * @param {Array|String} haystack
     * @param {Mixed} needle
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notInclude = function (exp, inc, msg) {
      new Assertion(exp, msg, assert.notInclude).not.include(inc);
    };
  
    /**
     * ### .match(value, regexp, [message])
     *
     * Asserts that `value` matches the regular expression `regexp`.
     *
     *     assert.match('foobar', /^foo/, 'regexp matches');
     *
     * @name match
     * @param {Mixed} value
     * @param {RegExp} regexp
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.match = function (exp, re, msg) {
      new Assertion(exp, msg).to.match(re);
    };
  
    /**
     * ### .notMatch(value, regexp, [message])
     *
     * Asserts that `value` does not match the regular expression `regexp`.
     *
     *     assert.notMatch('foobar', /^foo/, 'regexp does not match');
     *
     * @name notMatch
     * @param {Mixed} value
     * @param {RegExp} regexp
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notMatch = function (exp, re, msg) {
      new Assertion(exp, msg).to.not.match(re);
    };
  
    /**
     * ### .property(object, property, [message])
     *
     * Asserts that `object` has a property named by `property`.
     *
     *     assert.property({ tea: { green: 'matcha' }}, 'tea');
     *
     * @name property
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.property = function (obj, prop, msg) {
      new Assertion(obj, msg).to.have.property(prop);
    };
  
    /**
     * ### .notProperty(object, property, [message])
     *
     * Asserts that `object` does _not_ have a property named by `property`.
     *
     *     assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
     *
     * @name notProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.not.have.property(prop);
    };
  
    /**
     * ### .deepProperty(object, property, [message])
     *
     * Asserts that `object` has a property named by `property`, which can be a
     * string using dot- and bracket-notation for deep reference.
     *
     *     assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
     *
     * @name deepProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.deepProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.have.deep.property(prop);
    };
  
    /**
     * ### .notDeepProperty(object, property, [message])
     *
     * Asserts that `object` does _not_ have a property named by `property`, which
     * can be a string using dot- and bracket-notation for deep reference.
     *
     *     assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
     *
     * @name notDeepProperty
     * @param {Object} object
     * @param {String} property
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.notDeepProperty = function (obj, prop, msg) {
      new Assertion(obj, msg).to.not.have.deep.property(prop);
    };
  
    /**
     * ### .propertyVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property` with value given
     * by `value`.
     *
     *     assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
     *
     * @name propertyVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.propertyVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.have.property(prop, val);
    };
  
    /**
     * ### .propertyNotVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property`, but with a value
     * different from that given by `value`.
     *
     *     assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
     *
     * @name propertyNotVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.propertyNotVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.not.have.property(prop, val);
    };
  
    /**
     * ### .deepPropertyVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property` with value given
     * by `value`. `property` can use dot- and bracket-notation for deep
     * reference.
     *
     *     assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
     *
     * @name deepPropertyVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.deepPropertyVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.have.deep.property(prop, val);
    };
  
    /**
     * ### .deepPropertyNotVal(object, property, value, [message])
     *
     * Asserts that `object` has a property named by `property`, but with a value
     * different from that given by `value`. `property` can use dot- and
     * bracket-notation for deep reference.
     *
     *     assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
     *
     * @name deepPropertyNotVal
     * @param {Object} object
     * @param {String} property
     * @param {Mixed} value
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.deepPropertyNotVal = function (obj, prop, val, msg) {
      new Assertion(obj, msg).to.not.have.deep.property(prop, val);
    };
  
    /**
     * ### .lengthOf(object, length, [message])
     *
     * Asserts that `object` has a `length` property with the expected value.
     *
     *     assert.lengthOf([1,2,3], 3, 'array has length of 3');
     *     assert.lengthOf('foobar', 6, 'string has length of 6');
     *
     * @name lengthOf
     * @param {Mixed} object
     * @param {Number} length
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.lengthOf = function (exp, len, msg) {
      new Assertion(exp, msg).to.have.length(len);
    };
  
    /**
     * ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
     *
     * Asserts that `function` will throw an error that is an instance of
     * `constructor`, or alternately that it will throw an error with message
     * matching `regexp`.
     *
     *     assert.throws(fn, 'function throws a reference error');
     *     assert.throws(fn, /function throws a reference error/);
     *     assert.throws(fn, ReferenceError);
     *     assert.throws(fn, ReferenceError, 'function throws a reference error');
     *     assert.throws(fn, ReferenceError, /function throws a reference error/);
     *
     * @name throws
     * @alias throw
     * @alias Throw
     * @param {Function} function
     * @param {ErrorConstructor} constructor
     * @param {RegExp} regexp
     * @param {String} message
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @namespace Assert
     * @api public
     */
  
    assert.throws = function (fn, errt, errs, msg) {
      if ('string' === typeof errt || errt instanceof RegExp) {
        errs = errt;
        errt = null;
      }
  
      var assertErr = new Assertion(fn, msg).to.throw(errt, errs);
      return flag(assertErr, 'object');
    };
  
    /**
     * ### .doesNotThrow(function, [constructor/regexp], [message])
     *
     * Asserts that `function` will _not_ throw an error that is an instance of
     * `constructor`, or alternately that it will not throw an error with message
     * matching `regexp`.
     *
     *     assert.doesNotThrow(fn, Error, 'function does not throw');
     *
     * @name doesNotThrow
     * @param {Function} function
     * @param {ErrorConstructor} constructor
     * @param {RegExp} regexp
     * @param {String} message
     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
     * @namespace Assert
     * @api public
     */
  
    assert.doesNotThrow = function (fn, type, msg) {
      if ('string' === typeof type) {
        msg = type;
        type = null;
      }
  
      new Assertion(fn, msg).to.not.Throw(type);
    };
  
    /**
     * ### .operator(val1, operator, val2, [message])
     *
     * Compares two values using `operator`.
     *
     *     assert.operator(1, '<', 2, 'everything is ok');
     *     assert.operator(1, '>', 2, 'this will fail');
     *
     * @name operator
     * @param {Mixed} val1
     * @param {String} operator
     * @param {Mixed} val2
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.operator = function (val, operator, val2, msg) {
      var ok;
      switch(operator) {
        case '==':
          ok = val == val2;
          break;
        case '===':
          ok = val === val2;
          break;
        case '>':
          ok = val > val2;
          break;
        case '>=':
          ok = val >= val2;
          break;
        case '<':
          ok = val < val2;
          break;
        case '<=':
          ok = val <= val2;
          break;
        case '!=':
          ok = val != val2;
          break;
        case '!==':
          ok = val !== val2;
          break;
        default:
          throw new Error('Invalid operator "' + operator + '"');
      }
      var test = new Assertion(ok, msg);
      test.assert(
          true === flag(test, 'object')
        , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
        , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
    };
  
    /**
     * ### .closeTo(actual, expected, delta, [message])
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     assert.closeTo(1.5, 1, 0.5, 'numbers are close');
     *
     * @name closeTo
     * @param {Number} actual
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.closeTo = function (act, exp, delta, msg) {
      new Assertion(act, msg).to.be.closeTo(exp, delta);
    };
  
    /**
     * ### .approximately(actual, expected, delta, [message])
     *
     * Asserts that the target is equal `expected`, to within a +/- `delta` range.
     *
     *     assert.approximately(1.5, 1, 0.5, 'numbers are close');
     *
     * @name approximately
     * @param {Number} actual
     * @param {Number} expected
     * @param {Number} delta
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.approximately = function (act, exp, delta, msg) {
      new Assertion(act, msg).to.be.approximately(exp, delta);
    };
  
    /**
     * ### .sameMembers(set1, set2, [message])
     *
     * Asserts that `set1` and `set2` have the same members.
     * Order is not taken into account.
     *
     *     assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
     *
     * @name sameMembers
     * @param {Array} set1
     * @param {Array} set2
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.sameMembers = function (set1, set2, msg) {
      new Assertion(set1, msg).to.have.same.members(set2);
    }
  
    /**
     * ### .sameDeepMembers(set1, set2, [message])
     *
     * Asserts that `set1` and `set2` have the same members - using a deep equality checking.
     * Order is not taken into account.
     *
     *     assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members');
     *
     * @name sameDeepMembers
     * @param {Array} set1
     * @param {Array} set2
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.sameDeepMembers = function (set1, set2, msg) {
      new Assertion(set1, msg).to.have.same.deep.members(set2);
    }
  
    /**
     * ### .includeMembers(superset, subset, [message])
     *
     * Asserts that `subset` is included in `superset`.
     * Order is not taken into account.
     *
     *     assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
     *
     * @name includeMembers
     * @param {Array} superset
     * @param {Array} subset
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.includeMembers = function (superset, subset, msg) {
      new Assertion(superset, msg).to.include.members(subset);
    }
  
    /**
     * ### .includeDeepMembers(superset, subset, [message])
     *
     * Asserts that `subset` is included in `superset` - using deep equality checking.
     * Order is not taken into account.
     * Duplicates are ignored.
     *
     *     assert.includeDeepMembers([ {a: 1}, {b: 2}, {c: 3} ], [ {b: 2}, {a: 1}, {b: 2} ], 'include deep members');
     *
     * @name includeDeepMembers
     * @param {Array} superset
     * @param {Array} subset
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.includeDeepMembers = function (superset, subset, msg) {
      new Assertion(superset, msg).to.include.deep.members(subset);
    }
  
    /**
     * ### .oneOf(inList, list, [message])
     *
     * Asserts that non-object, non-array value `inList` appears in the flat array `list`.
     *
     *     assert.oneOf(1, [ 2, 1 ], 'Not found in list');
     *
     * @name oneOf
     * @param {*} inList
     * @param {Array<*>} list
     * @param {String} message
     * @namespace Assert
     * @api public
     */
  
    assert.oneOf = function (inList, list, msg) {
      new Assertion(inList, msg).to.be.oneOf(list);
    }
  
     /**
     * ### .changes(function, object, property)
     *
     * Asserts that a function changes the value of a property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 22 };
     *     assert.changes(fn, obj, 'val');
     *
     * @name changes
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.changes = function (fn, obj, prop) {
      new Assertion(fn).to.change(obj, prop);
    }
  
     /**
     * ### .doesNotChange(function, object, property)
     *
     * Asserts that a function does not changes the value of a property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { console.log('foo'); };
     *     assert.doesNotChange(fn, obj, 'val');
     *
     * @name doesNotChange
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.doesNotChange = function (fn, obj, prop) {
      new Assertion(fn).to.not.change(obj, prop);
    }
  
     /**
     * ### .increases(function, object, property)
     *
     * Asserts that a function increases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 13 };
     *     assert.increases(fn, obj, 'val');
     *
     * @name increases
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.increases = function (fn, obj, prop) {
      new Assertion(fn).to.increase(obj, prop);
    }
  
     /**
     * ### .doesNotIncrease(function, object, property)
     *
     * Asserts that a function does not increase object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 8 };
     *     assert.doesNotIncrease(fn, obj, 'val');
     *
     * @name doesNotIncrease
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.doesNotIncrease = function (fn, obj, prop) {
      new Assertion(fn).to.not.increase(obj, prop);
    }
  
     /**
     * ### .decreases(function, object, property)
     *
     * Asserts that a function decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 5 };
     *     assert.decreases(fn, obj, 'val');
     *
     * @name decreases
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.decreases = function (fn, obj, prop) {
      new Assertion(fn).to.decrease(obj, prop);
    }
  
     /**
     * ### .doesNotDecrease(function, object, property)
     *
     * Asserts that a function does not decreases an object property
     *
     *     var obj = { val: 10 };
     *     var fn = function() { obj.val = 15 };
     *     assert.doesNotDecrease(fn, obj, 'val');
     *
     * @name doesNotDecrease
     * @param {Function} modifier function
     * @param {Object} object
     * @param {String} property name
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.doesNotDecrease = function (fn, obj, prop) {
      new Assertion(fn).to.not.decrease(obj, prop);
    }
  
    /*!
     * ### .ifError(object)
     *
     * Asserts if value is not a false value, and throws if it is a true value.
     * This is added to allow for chai to be a drop-in replacement for Node's
     * assert class.
     *
     *     var err = new Error('I am a custom error');
     *     assert.ifError(err); // Rethrows err!
     *
     * @name ifError
     * @param {Object} object
     * @namespace Assert
     * @api public
     */
  
    assert.ifError = function (val) {
      if (val) {
        throw(val);
      }
    };
  
    /**
     * ### .isExtensible(object)
     *
     * Asserts that `object` is extensible (can have new properties added to it).
     *
     *     assert.isExtensible({});
     *
     * @name isExtensible
     * @alias extensible
     * @param {Object} object
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.isExtensible = function (obj, msg) {
      new Assertion(obj, msg).to.be.extensible;
    };
  
    /**
     * ### .isNotExtensible(object)
     *
     * Asserts that `object` is _not_ extensible.
     *
     *     var nonExtensibleObject = Object.preventExtensions({});
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.freese({});
     *
     *     assert.isNotExtensible(nonExtensibleObject);
     *     assert.isNotExtensible(sealedObject);
     *     assert.isNotExtensible(frozenObject);
     *
     * @name isNotExtensible
     * @alias notExtensible
     * @param {Object} object
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.isNotExtensible = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.extensible;
    };
  
    /**
     * ### .isSealed(object)
     *
     * Asserts that `object` is sealed (cannot have new properties added to it
     * and its existing properties cannot be removed).
     *
     *     var sealedObject = Object.seal({});
     *     var frozenObject = Object.seal({});
     *
     *     assert.isSealed(sealedObject);
     *     assert.isSealed(frozenObject);
     *
     * @name isSealed
     * @alias sealed
     * @param {Object} object
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.isSealed = function (obj, msg) {
      new Assertion(obj, msg).to.be.sealed;
    };
  
    /**
     * ### .isNotSealed(object)
     *
     * Asserts that `object` is _not_ sealed.
     *
     *     assert.isNotSealed({});
     *
     * @name isNotSealed
     * @alias notSealed
     * @param {Object} object
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.isNotSealed = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.sealed;
    };
  
    /**
     * ### .isFrozen(object)
     *
     * Asserts that `object` is frozen (cannot have new properties added to it
     * and its existing properties cannot be modified).
     *
     *     var frozenObject = Object.freeze({});
     *     assert.frozen(frozenObject);
     *
     * @name isFrozen
     * @alias frozen
     * @param {Object} object
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.isFrozen = function (obj, msg) {
      new Assertion(obj, msg).to.be.frozen;
    };
  
    /**
     * ### .isNotFrozen(object)
     *
     * Asserts that `object` is _not_ frozen.
     *
     *     assert.isNotFrozen({});
     *
     * @name isNotFrozen
     * @alias notFrozen
     * @param {Object} object
     * @param {String} message _optional_
     * @namespace Assert
     * @api public
     */
  
    assert.isNotFrozen = function (obj, msg) {
      new Assertion(obj, msg).to.not.be.frozen;
    };
  
    /*!
     * Aliases.
     */
  
    (function alias(name, as){
      assert[as] = assert[name];
      return alias;
    })
    ('isOk', 'ok')
    ('isNotOk', 'notOk')
    ('throws', 'throw')
    ('throws', 'Throw')
    ('isExtensible', 'extensible')
    ('isNotExtensible', 'notExtensible')
    ('isSealed', 'sealed')
    ('isNotSealed', 'notSealed')
    ('isFrozen', 'frozen')
    ('isNotFrozen', 'notFrozen');
  };
  
  },{}],219:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, util) {
    chai.expect = function (val, message) {
      return new chai.Assertion(val, message);
    };
  
    /**
     * ### .fail(actual, expected, [message], [operator])
     *
     * Throw a failure.
     *
     * @name fail
     * @param {Mixed} actual
     * @param {Mixed} expected
     * @param {String} message
     * @param {String} operator
     * @namespace Expect
     * @api public
     */
  
    chai.expect.fail = function (actual, expected, message, operator) {
      message = message || 'expect.fail()';
      throw new chai.AssertionError(message, {
          actual: actual
        , expected: expected
        , operator: operator
      }, chai.expect.fail);
    };
  };
  
  },{}],220:[function(require,module,exports){
  /*!
   * chai
   * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  module.exports = function (chai, util) {
    var Assertion = chai.Assertion;
  
    function loadShould () {
      // explicitly define this method as function as to have it's name to include as `ssfi`
      function shouldGetter() {
        if (this instanceof String || this instanceof Number || this instanceof Boolean ) {
          return new Assertion(this.valueOf(), null, shouldGetter);
        }
        return new Assertion(this, null, shouldGetter);
      }
      function shouldSetter(value) {
        // See https://github.com/chaijs/chai/issues/86: this makes
        // `whatever.should = someValue` actually set `someValue`, which is
        // especially useful for `global.should = require('chai').should()`.
        //
        // Note that we have to use [[DefineProperty]] instead of [[Put]]
        // since otherwise we would trigger this very setter!
        Object.defineProperty(this, 'should', {
          value: value,
          enumerable: true,
          configurable: true,
          writable: true
        });
      }
      // modify Object.prototype to have `should`
      Object.defineProperty(Object.prototype, 'should', {
        set: shouldSetter
        , get: shouldGetter
        , configurable: true
      });
  
      var should = {};
  
      /**
       * ### .fail(actual, expected, [message], [operator])
       *
       * Throw a failure.
       *
       * @name fail
       * @param {Mixed} actual
       * @param {Mixed} expected
       * @param {String} message
       * @param {String} operator
       * @namespace Should
       * @api public
       */
  
      should.fail = function (actual, expected, message, operator) {
        message = message || 'should.fail()';
        throw new chai.AssertionError(message, {
            actual: actual
          , expected: expected
          , operator: operator
        }, should.fail);
      };
  
      /**
       * ### .equal(actual, expected, [message])
       *
       * Asserts non-strict equality (`==`) of `actual` and `expected`.
       *
       *     should.equal(3, '3', '== coerces values to strings');
       *
       * @name equal
       * @param {Mixed} actual
       * @param {Mixed} expected
       * @param {String} message
       * @namespace Should
       * @api public
       */
  
      should.equal = function (val1, val2, msg) {
        new Assertion(val1, msg).to.equal(val2);
      };
  
      /**
       * ### .throw(function, [constructor/string/regexp], [string/regexp], [message])
       *
       * Asserts that `function` will throw an error that is an instance of
       * `constructor`, or alternately that it will throw an error with message
       * matching `regexp`.
       *
       *     should.throw(fn, 'function throws a reference error');
       *     should.throw(fn, /function throws a reference error/);
       *     should.throw(fn, ReferenceError);
       *     should.throw(fn, ReferenceError, 'function throws a reference error');
       *     should.throw(fn, ReferenceError, /function throws a reference error/);
       *
       * @name throw
       * @alias Throw
       * @param {Function} function
       * @param {ErrorConstructor} constructor
       * @param {RegExp} regexp
       * @param {String} message
       * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
       * @namespace Should
       * @api public
       */
  
      should.Throw = function (fn, errt, errs, msg) {
        new Assertion(fn, msg).to.Throw(errt, errs);
      };
  
      /**
       * ### .exist
       *
       * Asserts that the target is neither `null` nor `undefined`.
       *
       *     var foo = 'hi';
       *
       *     should.exist(foo, 'foo exists');
       *
       * @name exist
       * @namespace Should
       * @api public
       */
  
      should.exist = function (val, msg) {
        new Assertion(val, msg).to.exist;
      }
  
      // negation
      should.not = {}
  
      /**
       * ### .not.equal(actual, expected, [message])
       *
       * Asserts non-strict inequality (`!=`) of `actual` and `expected`.
       *
       *     should.not.equal(3, 4, 'these numbers are not equal');
       *
       * @name not.equal
       * @param {Mixed} actual
       * @param {Mixed} expected
       * @param {String} message
       * @namespace Should
       * @api public
       */
  
      should.not.equal = function (val1, val2, msg) {
        new Assertion(val1, msg).to.not.equal(val2);
      };
  
      /**
       * ### .throw(function, [constructor/regexp], [message])
       *
       * Asserts that `function` will _not_ throw an error that is an instance of
       * `constructor`, or alternately that it will not throw an error with message
       * matching `regexp`.
       *
       *     should.not.throw(fn, Error, 'function does not throw');
       *
       * @name not.throw
       * @alias not.Throw
       * @param {Function} function
       * @param {ErrorConstructor} constructor
       * @param {RegExp} regexp
       * @param {String} message
       * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
       * @namespace Should
       * @api public
       */
  
      should.not.Throw = function (fn, errt, errs, msg) {
        new Assertion(fn, msg).to.not.Throw(errt, errs);
      };
  
      /**
       * ### .not.exist
       *
       * Asserts that the target is neither `null` nor `undefined`.
       *
       *     var bar = null;
       *
       *     should.not.exist(bar, 'bar does not exist');
       *
       * @name not.exist
       * @namespace Should
       * @api public
       */
  
      should.not.exist = function (val, msg) {
        new Assertion(val, msg).to.not.exist;
      }
  
      should['throw'] = should['Throw'];
      should.not['throw'] = should.not['Throw'];
  
      return should;
    };
  
    chai.should = loadShould;
    chai.Should = loadShould;
  };
  
  },{}],221:[function(require,module,exports){
  /*!
   * Chai - addChainingMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependencies
   */
  
  var transferFlags = require('./transferFlags');
  var flag = require('./flag');
  var config = require('../config');
  
  /*!
   * Module variables
   */
  
  // Check whether `__proto__` is supported
  var hasProtoSupport = '__proto__' in Object;
  
  // Without `__proto__` support, this module will need to add properties to a function.
  // However, some Function.prototype methods cannot be overwritten,
  // and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).
  var excludeNames = /^(?:length|name|arguments|caller)$/;
  
  // Cache `Function` properties
  var call  = Function.prototype.call,
      apply = Function.prototype.apply;
  
  /**
   * ### addChainableMethod (ctx, name, method, chainingBehavior)
   *
   * Adds a method to an object, such that the method can also be chained.
   *
   *     utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.equal(str);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);
   *
   * The result can then be used as both a method assertion, executing both `method` and
   * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.
   *
   *     expect(fooStr).to.be.foo('bar');
   *     expect(fooStr).to.be.foo.equal('foo');
   *
   * @param {Object} ctx object to which the method is added
   * @param {String} name of method to add
   * @param {Function} method function to be used for `name`, when called
   * @param {Function} chainingBehavior function to be called every time the property is accessed
   * @namespace Utils
   * @name addChainableMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method, chainingBehavior) {
    if (typeof chainingBehavior !== 'function') {
      chainingBehavior = function () { };
    }
  
    var chainableBehavior = {
        method: method
      , chainingBehavior: chainingBehavior
    };
  
    // save the methods so we can overwrite them later, if we need to.
    if (!ctx.__methods) {
      ctx.__methods = {};
    }
    ctx.__methods[name] = chainableBehavior;
  
    Object.defineProperty(ctx, name,
      { get: function () {
          chainableBehavior.chainingBehavior.call(this);
  
          var assert = function assert() {
            var old_ssfi = flag(this, 'ssfi');
            if (old_ssfi && config.includeStack === false)
              flag(this, 'ssfi', assert);
            var result = chainableBehavior.method.apply(this, arguments);
            return result === undefined ? this : result;
          };
  
          // Use `__proto__` if available
          if (hasProtoSupport) {
            // Inherit all properties from the object by replacing the `Function` prototype
            var prototype = assert.__proto__ = Object.create(this);
            // Restore the `call` and `apply` methods from `Function`
            prototype.call = call;
            prototype.apply = apply;
          }
          // Otherwise, redefine all properties (slow!)
          else {
            var asserterNames = Object.getOwnPropertyNames(ctx);
            asserterNames.forEach(function (asserterName) {
              if (!excludeNames.test(asserterName)) {
                var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
                Object.defineProperty(assert, asserterName, pd);
              }
            });
          }
  
          transferFlags(this, assert);
          return assert;
        }
      , configurable: true
    });
  };
  
  },{"../config":216,"./flag":225,"./transferFlags":241}],222:[function(require,module,exports){
  /*!
   * Chai - addMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var config = require('../config');
  
  /**
   * ### .addMethod (ctx, name, method)
   *
   * Adds a method to the prototype of an object.
   *
   *     utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.equal(str);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addMethod('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(fooStr).to.be.foo('bar');
   *
   * @param {Object} ctx object to which the method is added
   * @param {String} name of method to add
   * @param {Function} method function to be used for name
   * @namespace Utils
   * @name addMethod
   * @api public
   */
  var flag = require('./flag');
  
  module.exports = function (ctx, name, method) {
    ctx[name] = function () {
      var old_ssfi = flag(this, 'ssfi');
      if (old_ssfi && config.includeStack === false)
        flag(this, 'ssfi', ctx[name]);
      var result = method.apply(this, arguments);
      return result === undefined ? this : result;
    };
  };
  
  },{"../config":216,"./flag":225}],223:[function(require,module,exports){
  /*!
   * Chai - addProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var config = require('../config');
  var flag = require('./flag');
  
  /**
   * ### addProperty (ctx, name, getter)
   *
   * Adds a property to the prototype of an object.
   *
   *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {
   *       var obj = utils.flag(this, 'object');
   *       new chai.Assertion(obj).to.be.instanceof(Foo);
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.addProperty('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.be.foo;
   *
   * @param {Object} ctx object to which the property is added
   * @param {String} name of property to add
   * @param {Function} getter function to be used for name
   * @namespace Utils
   * @name addProperty
   * @api public
   */
  
  module.exports = function (ctx, name, getter) {
    Object.defineProperty(ctx, name,
      { get: function addProperty() {
          var old_ssfi = flag(this, 'ssfi');
          if (old_ssfi && config.includeStack === false)
            flag(this, 'ssfi', addProperty);
  
          var result = getter.call(this);
          return result === undefined ? this : result;
        }
      , configurable: true
    });
  };
  
  },{"../config":216,"./flag":225}],224:[function(require,module,exports){
  /*!
   * Chai - expectTypes utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### expectTypes(obj, types)
   *
   * Ensures that the object being tested against is of a valid type.
   *
   *     utils.expectTypes(this, ['array', 'object', 'string']);
   *
   * @param {Mixed} obj constructed Assertion
   * @param {Array} type A list of allowed types for this assertion
   * @namespace Utils
   * @name expectTypes
   * @api public
   */
  
  var AssertionError = require('assertion-error');
  var flag = require('./flag');
  var type = require('type-detect');
  
  module.exports = function (obj, types) {
    var obj = flag(obj, 'object');
    types = types.map(function (t) { return t.toLowerCase(); });
    types.sort();
  
    // Transforms ['lorem', 'ipsum'] into 'a lirum, or an ipsum'
    var str = types.map(function (t, index) {
      var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a';
      var or = types.length > 1 && index === types.length - 1 ? 'or ' : '';
      return or + art + ' ' + t;
    }).join(', ');
  
    if (!types.some(function (expected) { return type(obj) === expected; })) {
      throw new AssertionError(
        'object tested must be ' + str + ', but ' + type(obj) + ' given'
      );
    }
  };
  
  },{"./flag":225,"assertion-error":7,"type-detect":263}],225:[function(require,module,exports){
  /*!
   * Chai - flag utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### flag(object, key, [value])
   *
   * Get or set a flag value on an object. If a
   * value is provided it will be set, else it will
   * return the currently set value or `undefined` if
   * the value is not set.
   *
   *     utils.flag(this, 'foo', 'bar'); // setter
   *     utils.flag(this, 'foo'); // getter, returns `bar`
   *
   * @param {Object} object constructed Assertion
   * @param {String} key
   * @param {Mixed} value (optional)
   * @namespace Utils
   * @name flag
   * @api private
   */
  
  module.exports = function (obj, key, value) {
    var flags = obj.__flags || (obj.__flags = Object.create(null));
    if (arguments.length === 3) {
      flags[key] = value;
    } else {
      return flags[key];
    }
  };
  
  },{}],226:[function(require,module,exports){
  /*!
   * Chai - getActual utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * # getActual(object, [actual])
   *
   * Returns the `actual` value for an Assertion
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   * @namespace Utils
   * @name getActual
   */
  
  module.exports = function (obj, args) {
    return args.length > 4 ? args[4] : obj._obj;
  };
  
  },{}],227:[function(require,module,exports){
  /*!
   * Chai - getEnumerableProperties utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### .getEnumerableProperties(object)
   *
   * This allows the retrieval of enumerable property names of an object,
   * inherited or not.
   *
   * @param {Object} object
   * @returns {Array}
   * @namespace Utils
   * @name getEnumerableProperties
   * @api public
   */
  
  module.exports = function getEnumerableProperties(object) {
    var result = [];
    for (var name in object) {
      result.push(name);
    }
    return result;
  };
  
  },{}],228:[function(require,module,exports){
  /*!
   * Chai - message composition utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var flag = require('./flag')
    , getActual = require('./getActual')
    , inspect = require('./inspect')
    , objDisplay = require('./objDisplay');
  
  /**
   * ### .getMessage(object, message, negateMessage)
   *
   * Construct the error message based on flags
   * and template tags. Template tags will return
   * a stringified inspection of the object referenced.
   *
   * Message template tags:
   * - `#{this}` current asserted object
   * - `#{act}` actual value
   * - `#{exp}` expected value
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   * @namespace Utils
   * @name getMessage
   * @api public
   */
  
  module.exports = function (obj, args) {
    var negate = flag(obj, 'negate')
      , val = flag(obj, 'object')
      , expected = args[3]
      , actual = getActual(obj, args)
      , msg = negate ? args[2] : args[1]
      , flagMsg = flag(obj, 'message');
  
    if(typeof msg === "function") msg = msg();
    msg = msg || '';
    msg = msg
      .replace(/#\{this\}/g, function () { return objDisplay(val); })
      .replace(/#\{act\}/g, function () { return objDisplay(actual); })
      .replace(/#\{exp\}/g, function () { return objDisplay(expected); });
  
    return flagMsg ? flagMsg + ': ' + msg : msg;
  };
  
  },{"./flag":225,"./getActual":226,"./inspect":235,"./objDisplay":236}],229:[function(require,module,exports){
  /*!
   * Chai - getName utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * # getName(func)
   *
   * Gets the name of a function, in a cross-browser way.
   *
   * @param {Function} a function (usually a constructor)
   * @namespace Utils
   * @name getName
   */
  
  module.exports = function (func) {
    if (func.name) return func.name;
  
    var match = /^\s?function ([^(]*)\(/.exec(func);
    return match && match[1] ? match[1] : "";
  };
  
  },{}],230:[function(require,module,exports){
  /*!
   * Chai - getPathInfo utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var hasProperty = require('./hasProperty');
  
  /**
   * ### .getPathInfo(path, object)
   *
   * This allows the retrieval of property info in an
   * object given a string path.
   *
   * The path info consists of an object with the
   * following properties:
   *
   * * parent - The parent object of the property referenced by `path`
   * * name - The name of the final property, a number if it was an array indexer
   * * value - The value of the property, if it exists, otherwise `undefined`
   * * exists - Whether the property exists or not
   *
   * @param {String} path
   * @param {Object} object
   * @returns {Object} info
   * @namespace Utils
   * @name getPathInfo
   * @api public
   */
  
  module.exports = function getPathInfo(path, obj) {
    var parsed = parsePath(path),
        last = parsed[parsed.length - 1];
  
    var info = {
      parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj,
      name: last.p || last.i,
      value: _getPathValue(parsed, obj)
    };
    info.exists = hasProperty(info.name, info.parent);
  
    return info;
  };
  
  
  /*!
   * ## parsePath(path)
   *
   * Helper function used to parse string object
   * paths. Use in conjunction with `_getPathValue`.
   *
   *      var parsed = parsePath('myobject.property.subprop');
   *
   * ### Paths:
   *
   * * Can be as near infinitely deep and nested
   * * Arrays are also valid using the formal `myobject.document[3].property`.
   * * Literal dots and brackets (not delimiter) must be backslash-escaped.
   *
   * @param {String} path
   * @returns {Object} parsed
   * @api private
   */
  
  function parsePath (path) {
    var str = path.replace(/([^\\])\[/g, '$1.[')
      , parts = str.match(/(\\\.|[^.]+?)+/g);
    return parts.map(function (value) {
      var re = /^\[(\d+)\]$/
        , mArr = re.exec(value);
      if (mArr) return { i: parseFloat(mArr[1]) };
      else return { p: value.replace(/\\([.\[\]])/g, '$1') };
    });
  }
  
  
  /*!
   * ## _getPathValue(parsed, obj)
   *
   * Helper companion function for `.parsePath` that returns
   * the value located at the parsed address.
   *
   *      var value = getPathValue(parsed, obj);
   *
   * @param {Object} parsed definition from `parsePath`.
   * @param {Object} object to search against
   * @param {Number} object to search against
   * @returns {Object|Undefined} value
   * @api private
   */
  
  function _getPathValue (parsed, obj, index) {
    var tmp = obj
      , res;
  
    index = (index === undefined ? parsed.length : index);
  
    for (var i = 0, l = index; i < l; i++) {
      var part = parsed[i];
      if (tmp) {
        if ('undefined' !== typeof part.p)
          tmp = tmp[part.p];
        else if ('undefined' !== typeof part.i)
          tmp = tmp[part.i];
        if (i == (l - 1)) res = tmp;
      } else {
        res = undefined;
      }
    }
    return res;
  }
  
  },{"./hasProperty":233}],231:[function(require,module,exports){
  /*!
   * Chai - getPathValue utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * @see https://github.com/logicalparadox/filtr
   * MIT Licensed
   */
  
  var getPathInfo = require('./getPathInfo');
  
  /**
   * ### .getPathValue(path, object)
   *
   * This allows the retrieval of values in an
   * object given a string path.
   *
   *     var obj = {
   *         prop1: {
   *             arr: ['a', 'b', 'c']
   *           , str: 'Hello'
   *         }
   *       , prop2: {
   *             arr: [ { nested: 'Universe' } ]
   *           , str: 'Hello again!'
   *         }
   *     }
   *
   * The following would be the results.
   *
   *     getPathValue('prop1.str', obj); // Hello
   *     getPathValue('prop1.att[2]', obj); // b
   *     getPathValue('prop2.arr[0].nested', obj); // Universe
   *
   * @param {String} path
   * @param {Object} object
   * @returns {Object} value or `undefined`
   * @namespace Utils
   * @name getPathValue
   * @api public
   */
  module.exports = function(path, obj) {
    var info = getPathInfo(path, obj);
    return info.value;
  };
  
  },{"./getPathInfo":230}],232:[function(require,module,exports){
  /*!
   * Chai - getProperties utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### .getProperties(object)
   *
   * This allows the retrieval of property names of an object, enumerable or not,
   * inherited or not.
   *
   * @param {Object} object
   * @returns {Array}
   * @namespace Utils
   * @name getProperties
   * @api public
   */
  
  module.exports = function getProperties(object) {
    var result = Object.getOwnPropertyNames(object);
  
    function addProperty(property) {
      if (result.indexOf(property) === -1) {
        result.push(property);
      }
    }
  
    var proto = Object.getPrototypeOf(object);
    while (proto !== null) {
      Object.getOwnPropertyNames(proto).forEach(addProperty);
      proto = Object.getPrototypeOf(proto);
    }
  
    return result;
  };
  
  },{}],233:[function(require,module,exports){
  /*!
   * Chai - hasProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  var type = require('type-detect');
  
  /**
   * ### .hasProperty(object, name)
   *
   * This allows checking whether an object has
   * named property or numeric array index.
   *
   * Basically does the same thing as the `in`
   * operator but works properly with natives
   * and null/undefined values.
   *
   *     var obj = {
   *         arr: ['a', 'b', 'c']
   *       , str: 'Hello'
   *     }
   *
   * The following would be the results.
   *
   *     hasProperty('str', obj);  // true
   *     hasProperty('constructor', obj);  // true
   *     hasProperty('bar', obj);  // false
   *
   *     hasProperty('length', obj.str); // true
   *     hasProperty(1, obj.str);  // true
   *     hasProperty(5, obj.str);  // false
   *
   *     hasProperty('length', obj.arr);  // true
   *     hasProperty(2, obj.arr);  // true
   *     hasProperty(3, obj.arr);  // false
   *
   * @param {Objuect} object
   * @param {String|Number} name
   * @returns {Boolean} whether it exists
   * @namespace Utils
   * @name getPathInfo
   * @api public
   */
  
  var literals = {
      'number': Number
    , 'string': String
  };
  
  module.exports = function hasProperty(name, obj) {
    var ot = type(obj);
  
    // Bad Object, obviously no props at all
    if(ot === 'null' || ot === 'undefined')
      return false;
  
    // The `in` operator does not work with certain literals
    // box these before the check
    if(literals[ot] && typeof obj !== 'object')
      obj = new literals[ot](obj);
  
    return name in obj;
  };
  
  },{"type-detect":263}],234:[function(require,module,exports){
  arguments[4][35][0].apply(exports,arguments)
  },{"./addChainableMethod":221,"./addMethod":222,"./addProperty":223,"./expectTypes":224,"./flag":225,"./getActual":226,"./getMessage":228,"./getName":229,"./getPathInfo":230,"./getPathValue":231,"./hasProperty":233,"./inspect":235,"./objDisplay":236,"./overwriteChainableMethod":237,"./overwriteMethod":238,"./overwriteProperty":239,"./test":240,"./transferFlags":241,"C:\\Users\\Olivier\\Projets\\LD34\\PostLD34\\git\\LD34\\node_modules\\chai\\lib\\chai\\utils\\index.js":35,"deep-eql":47,"type-detect":263}],235:[function(require,module,exports){
  // This is (almost) directly from Node.js utils
  // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
  
  var getName = require('./getName');
  var getProperties = require('./getProperties');
  var getEnumerableProperties = require('./getEnumerableProperties');
  
  module.exports = inspect;
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Boolean} showHidden Flag that shows hidden (not enumerable)
   *    properties of objects.
   * @param {Number} depth Depth in which to descend in object. Default is 2.
   * @param {Boolean} colors Flag to turn on ANSI escape codes to color the
   *    output. Default is false (no coloring).
   * @namespace Utils
   * @name inspect
   */
  function inspect(obj, showHidden, depth, colors) {
    var ctx = {
      showHidden: showHidden,
      seen: [],
      stylize: function (str) { return str; }
    };
    return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
  }
  
  // Returns true if object is a DOM element.
  var isDOMElement = function (object) {
    if (typeof HTMLElement === 'object') {
      return object instanceof HTMLElement;
    } else {
      return object &&
        typeof object === 'object' &&
        object.nodeType === 1 &&
        typeof object.nodeName === 'string';
    }
  };
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (value && typeof value.inspect === 'function' &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes);
      if (typeof ret !== 'string') {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // If this is a DOM element, try to get the outer HTML.
    if (isDOMElement(value)) {
      if ('outerHTML' in value) {
        return value.outerHTML;
        // This value does not have an outerHTML attribute,
        //   it could still be an XML element
      } else {
        // Attempt to serialize it
        try {
          if (document.xmlVersion) {
            var xmlSerializer = new XMLSerializer();
            return xmlSerializer.serializeToString(value);
          } else {
            // Firefox 11- do not support outerHTML
            //   It does, however, support innerHTML
            //   Use the following to render the element
            var ns = "http://www.w3.org/1999/xhtml";
            var container = document.createElementNS(ns, '_');
  
            container.appendChild(value.cloneNode(false));
            html = container.innerHTML
              .replace('><', '>' + value.innerHTML + '<');
            container.innerHTML = '';
            return html;
          }
        } catch (err) {
          // This could be a non-native DOM implementation,
          //   continue with the normal flow:
          //   printing the element as if it is an object.
        }
      }
    }
  
    // Look up the keys of the object.
    var visibleKeys = getEnumerableProperties(value);
    var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
  
    // Some type of object without properties can be shortcutted.
    // In IE, errors have a single `stack` property, or if they are vanilla `Error`,
    // a `stack` plus `description` property; ignore those for consistency.
    if (keys.length === 0 || (isError(value) && (
        (keys.length === 1 && keys[0] === 'stack') ||
        (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
       ))) {
      if (typeof value === 'function') {
        var name = getName(value);
        var nameSuffix = name ? ': ' + name : '';
        return ctx.stylize('[Function' + nameSuffix + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (typeof value === 'function') {
      var name = getName(value);
      var nameSuffix = name ? ': ' + name : '';
      base = ' [Function' + nameSuffix + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      return formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    switch (typeof value) {
      case 'undefined':
        return ctx.stylize('undefined', 'undefined');
  
      case 'string':
        var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                                 .replace(/'/g, "\\'")
                                                 .replace(/\\"/g, '"') + '\'';
        return ctx.stylize(simple, 'string');
  
      case 'number':
        if (value === 0 && (1/value) === -Infinity) {
          return ctx.stylize('-0', 'number');
        }
        return ctx.stylize('' + value, 'number');
  
      case 'boolean':
        return ctx.stylize('' + value, 'boolean');
    }
    // For some reason typeof null is "object", so special case here.
    if (value === null) {
      return ctx.stylize('null', 'null');
    }
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (Object.prototype.hasOwnProperty.call(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str;
    if (value.__lookupGetter__) {
      if (value.__lookupGetter__(key)) {
        if (value.__lookupSetter__(key)) {
          str = ctx.stylize('[Getter/Setter]', 'special');
        } else {
          str = ctx.stylize('[Getter]', 'special');
        }
      } else {
        if (value.__lookupSetter__(key)) {
          str = ctx.stylize('[Setter]', 'special');
        }
      }
    }
    if (visibleKeys.indexOf(key) < 0) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(value[key]) < 0) {
        if (recurseTimes === null) {
          str = formatValue(ctx, value[key], null);
        } else {
          str = formatValue(ctx, value[key], recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (typeof name === 'undefined') {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  function isArray(ar) {
    return Array.isArray(ar) ||
           (typeof ar === 'object' && objectToString(ar) === '[object Array]');
  }
  
  function isRegExp(re) {
    return typeof re === 'object' && objectToString(re) === '[object RegExp]';
  }
  
  function isDate(d) {
    return typeof d === 'object' && objectToString(d) === '[object Date]';
  }
  
  function isError(e) {
    return typeof e === 'object' && objectToString(e) === '[object Error]';
  }
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  },{"./getEnumerableProperties":227,"./getName":229,"./getProperties":232}],236:[function(require,module,exports){
  /*!
   * Chai - flag utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var inspect = require('./inspect');
  var config = require('../config');
  
  /**
   * ### .objDisplay (object)
   *
   * Determines if an object or an array matches
   * criteria to be inspected in-line for error
   * messages or should be truncated.
   *
   * @param {Mixed} javascript object to inspect
   * @name objDisplay
   * @namespace Utils
   * @api public
   */
  
  module.exports = function (obj) {
    var str = inspect(obj)
      , type = Object.prototype.toString.call(obj);
  
    if (config.truncateThreshold && str.length >= config.truncateThreshold) {
      if (type === '[object Function]') {
        return !obj.name || obj.name === ''
          ? '[Function]'
          : '[Function: ' + obj.name + ']';
      } else if (type === '[object Array]') {
        return '[ Array(' + obj.length + ') ]';
      } else if (type === '[object Object]') {
        var keys = Object.keys(obj)
          , kstr = keys.length > 2
            ? keys.splice(0, 2).join(', ') + ', ...'
            : keys.join(', ');
        return '{ Object (' + kstr + ') }';
      } else {
        return str;
      }
    } else {
      return str;
    }
  };
  
  },{"../config":216,"./inspect":235}],237:[function(require,module,exports){
  /*!
   * Chai - overwriteChainableMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteChainableMethod (ctx, name, method, chainingBehavior)
   *
   * Overwites an already existing chainable method
   * and provides access to the previous function or
   * property.  Must return functions to be used for
   * name.
   *
   *     utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
   *       function (_super) {
   *       }
   *     , function (_super) {
   *       }
   *     );
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteChainableMethod('foo', fn, fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.have.length(3);
   *     expect(myFoo).to.have.length.above(3);
   *
   * @param {Object} ctx object whose method / property is to be overwritten
   * @param {String} name of method / property to overwrite
   * @param {Function} method function that returns a function to be used for name
   * @param {Function} chainingBehavior function that returns a function to be used for property
   * @namespace Utils
   * @name overwriteChainableMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method, chainingBehavior) {
    var chainableBehavior = ctx.__methods[name];
  
    var _chainingBehavior = chainableBehavior.chainingBehavior;
    chainableBehavior.chainingBehavior = function () {
      var result = chainingBehavior(_chainingBehavior).call(this);
      return result === undefined ? this : result;
    };
  
    var _method = chainableBehavior.method;
    chainableBehavior.method = function () {
      var result = method(_method).apply(this, arguments);
      return result === undefined ? this : result;
    };
  };
  
  },{}],238:[function(require,module,exports){
  /*!
   * Chai - overwriteMethod utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteMethod (ctx, name, fn)
   *
   * Overwites an already existing method and provides
   * access to previous function. Must return function
   * to be used for name.
   *
   *     utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {
   *       return function (str) {
   *         var obj = utils.flag(this, 'object');
   *         if (obj instanceof Foo) {
   *           new chai.Assertion(obj.value).to.equal(str);
   *         } else {
   *           _super.apply(this, arguments);
   *         }
   *       }
   *     });
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteMethod('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.equal('bar');
   *
   * @param {Object} ctx object whose method is to be overwritten
   * @param {String} name of method to overwrite
   * @param {Function} method function that returns a function to be used for name
   * @namespace Utils
   * @name overwriteMethod
   * @api public
   */
  
  module.exports = function (ctx, name, method) {
    var _method = ctx[name]
      , _super = function () { return this; };
  
    if (_method && 'function' === typeof _method)
      _super = _method;
  
    ctx[name] = function () {
      var result = method(_super).apply(this, arguments);
      return result === undefined ? this : result;
    }
  };
  
  },{}],239:[function(require,module,exports){
  /*!
   * Chai - overwriteProperty utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### overwriteProperty (ctx, name, fn)
   *
   * Overwites an already existing property getter and provides
   * access to previous value. Must return function to use as getter.
   *
   *     utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {
   *       return function () {
   *         var obj = utils.flag(this, 'object');
   *         if (obj instanceof Foo) {
   *           new chai.Assertion(obj.name).to.equal('bar');
   *         } else {
   *           _super.call(this);
   *         }
   *       }
   *     });
   *
   *
   * Can also be accessed directly from `chai.Assertion`.
   *
   *     chai.Assertion.overwriteProperty('foo', fn);
   *
   * Then can be used as any other assertion.
   *
   *     expect(myFoo).to.be.ok;
   *
   * @param {Object} ctx object whose property is to be overwritten
   * @param {String} name of property to overwrite
   * @param {Function} getter function that returns a getter function to be used for name
   * @namespace Utils
   * @name overwriteProperty
   * @api public
   */
  
  module.exports = function (ctx, name, getter) {
    var _get = Object.getOwnPropertyDescriptor(ctx, name)
      , _super = function () {};
  
    if (_get && 'function' === typeof _get.get)
      _super = _get.get
  
    Object.defineProperty(ctx, name,
      { get: function () {
          var result = getter(_super).call(this);
          return result === undefined ? this : result;
        }
      , configurable: true
    });
  };
  
  },{}],240:[function(require,module,exports){
  /*!
   * Chai - test utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Module dependancies
   */
  
  var flag = require('./flag');
  
  /**
   * # test(object, expression)
   *
   * Test and object for expression.
   *
   * @param {Object} object (constructed Assertion)
   * @param {Arguments} chai.Assertion.prototype.assert arguments
   * @namespace Utils
   * @name test
   */
  
  module.exports = function (obj, args) {
    var negate = flag(obj, 'negate')
      , expr = args[0];
    return negate ? !expr : expr;
  };
  
  },{"./flag":225}],241:[function(require,module,exports){
  /*!
   * Chai - transferFlags utility
   * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /**
   * ### transferFlags(assertion, object, includeAll = true)
   *
   * Transfer all the flags for `assertion` to `object`. If
   * `includeAll` is set to `false`, then the base Chai
   * assertion flags (namely `object`, `ssfi`, and `message`)
   * will not be transferred.
   *
   *
   *     var newAssertion = new Assertion();
   *     utils.transferFlags(assertion, newAssertion);
   *
   *     var anotherAsseriton = new Assertion(myObj);
   *     utils.transferFlags(assertion, anotherAssertion, false);
   *
   * @param {Assertion} assertion the assertion to transfer the flags from
   * @param {Object} object the object to transfer the flags to; usually a new assertion
   * @param {Boolean} includeAll
   * @namespace Utils
   * @name transferFlags
   * @api private
   */
  
  module.exports = function (assertion, object, includeAll) {
    var flags = assertion.__flags || (assertion.__flags = Object.create(null));
  
    if (!object.__flags) {
      object.__flags = Object.create(null);
    }
  
    includeAll = arguments.length === 3 ? includeAll : true;
  
    for (var flag in flags) {
      if (includeAll ||
          (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
        object.__flags[flag] = flags[flag];
      }
    }
  };
  
  },{}],242:[function(require,module,exports){
  'use strict';
  var strictUriEncode = require('strict-uri-encode');
  
  exports.extract = function (str) {
  	return str.split('?')[1] || '';
  };
  
  exports.parse = function (str) {
  	if (typeof str !== 'string') {
  		return {};
  	}
  
  	str = str.trim().replace(/^(\?|#|&)/, '');
  
  	if (!str) {
  		return {};
  	}
  
  	return str.split('&').reduce(function (ret, param) {
  		var parts = param.replace(/\+/g, ' ').split('=');
  		// Firefox (pre 40) decodes `%3D` to `=`
  		// https://github.com/sindresorhus/query-string/pull/37
  		var key = parts.shift();
  		var val = parts.length > 0 ? parts.join('=') : undefined;
  
  		key = decodeURIComponent(key);
  
  		// missing `=` should be `null`:
  		// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
  		val = val === undefined ? null : decodeURIComponent(val);
  
  		if (!ret.hasOwnProperty(key)) {
  			ret[key] = val;
  		} else if (Array.isArray(ret[key])) {
  			ret[key].push(val);
  		} else {
  			ret[key] = [ret[key], val];
  		}
  
  		return ret;
  	}, {});
  };
  
  exports.stringify = function (obj) {
  	return obj ? Object.keys(obj).sort().map(function (key) {
  		var val = obj[key];
  
  		if (Array.isArray(val)) {
  			return val.sort().map(function (val2) {
  				return strictUriEncode(key) + '=' + strictUriEncode(val2);
  			}).join('&');
  		}
  
  		return strictUriEncode(key) + '=' + strictUriEncode(val);
  	}).filter(function (x) {
  		return x.length > 0;
  	}).join('&') : '';
  };
  
  },{"strict-uri-encode":259}],243:[function(require,module,exports){
  /**
   * Expose `requestAnimationFrame()`.
   */
  
  exports = module.exports = window.requestAnimationFrame
    || window.webkitRequestAnimationFrame
    || window.mozRequestAnimationFrame
    || window.oRequestAnimationFrame
    || window.msRequestAnimationFrame
    || fallback;
  
  /**
   * Fallback implementation.
   */
  
  var prev = new Date().getTime();
  function fallback(fn) {
    var curr = new Date().getTime();
    var ms = Math.max(0, 16 - (curr - prev));
    var req = setTimeout(fn, ms);
    prev = curr;
    return req;
  }
  
  /**
   * Cancel.
   */
  
  var cancel = window.cancelAnimationFrame
    || window.webkitCancelAnimationFrame
    || window.mozCancelAnimationFrame
    || window.oCancelAnimationFrame
    || window.msCancelAnimationFrame
    || window.clearTimeout;
  
  exports.cancel = function(id){
    cancel.call(window, id);
  };
  
  },{}],244:[function(require,module,exports){
  var cross = require('gl-vec3/cross');
  var dot = require('gl-vec3/dot');
  var sub = require('gl-vec3/subtract');
  
  var EPSILON = 0.000001;
  var edge1 = [0,0,0];
  var edge2 = [0,0,0];
  var tvec = [0,0,0];
  var pvec = [0,0,0];
  var qvec = [0,0,0];
  
  module.exports = intersectTriangle;
  
  function intersectTriangle (out, pt, dir, tri) {
      sub(edge1, tri[1], tri[0]);
      sub(edge2, tri[2], tri[0]);
      
      cross(pvec, dir, edge2);
      var det = dot(edge1, pvec);
      
      if (det < EPSILON) return null;
      sub(tvec, pt, tri[0]);
      var u = dot(tvec, pvec);
      if (u < 0 || u > det) return null;
      cross(qvec, tvec, edge1);
      var v = dot(dir, qvec);
      if (v < 0 || u + v > det) return null;
      
      var t = dot(edge2, qvec) / det;
      out[0] = pt[0] + t * dir[0];
      out[1] = pt[1] + t * dir[1];
      out[2] = pt[2] + t * dir[2];
      return out;
  }
  
  },{"gl-vec3/cross":146,"gl-vec3/dot":149,"gl-vec3/subtract":170}],245:[function(require,module,exports){
  module.exports = require("./lib/_stream_duplex.js")
  
  },{"./lib/_stream_duplex.js":246}],246:[function(require,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // a duplex stream is just a stream that is both readable and writable.
  // Since JS doesn't have multiple prototypal inheritance, this class
  // prototypally inherits from Readable, and then parasitically from
  // Writable.
  
  module.exports = Duplex;
  
  /*<replacement>*/
  var objectKeys = Object.keys || function (obj) {
    var keys = [];
    for (var key in obj) keys.push(key);
    return keys;
  }
  /*</replacement>*/
  
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  var Readable = require('./_stream_readable');
  var Writable = require('./_stream_writable');
  
  util.inherits(Duplex, Readable);
  
  forEach(objectKeys(Writable.prototype), function(method) {
    if (!Duplex.prototype[method])
      Duplex.prototype[method] = Writable.prototype[method];
  });
  
  function Duplex(options) {
    if (!(this instanceof Duplex))
      return new Duplex(options);
  
    Readable.call(this, options);
    Writable.call(this, options);
  
    if (options && options.readable === false)
      this.readable = false;
  
    if (options && options.writable === false)
      this.writable = false;
  
    this.allowHalfOpen = true;
    if (options && options.allowHalfOpen === false)
      this.allowHalfOpen = false;
  
    this.once('end', onend);
  }
  
  // the no-half-open enforcer
  function onend() {
    // if we allow half-open state, or if the writable side ended,
    // then we're ok.
    if (this.allowHalfOpen || this._writableState.ended)
      return;
  
    // no more data can be written.
    // But allow more writes to happen in this tick.
    process.nextTick(this.end.bind(this));
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  }).call(this,require('_process'))
  },{"./_stream_readable":248,"./_stream_writable":250,"_process":11,"core-util-is":43,"inherits":194}],247:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // a passthrough stream.
  // basically just the most minimal sort of Transform stream.
  // Every written chunk gets output as-is.
  
  module.exports = PassThrough;
  
  var Transform = require('./_stream_transform');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  util.inherits(PassThrough, Transform);
  
  function PassThrough(options) {
    if (!(this instanceof PassThrough))
      return new PassThrough(options);
  
    Transform.call(this, options);
  }
  
  PassThrough.prototype._transform = function(chunk, encoding, cb) {
    cb(null, chunk);
  };
  
  },{"./_stream_transform":249,"core-util-is":43,"inherits":194}],248:[function(require,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  module.exports = Readable;
  
  /*<replacement>*/
  var isArray = require('isarray');
  /*</replacement>*/
  
  
  /*<replacement>*/
  var Buffer = require('buffer').Buffer;
  /*</replacement>*/
  
  Readable.ReadableState = ReadableState;
  
  var EE = require('events').EventEmitter;
  
  /*<replacement>*/
  if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
    return emitter.listeners(type).length;
  };
  /*</replacement>*/
  
  var Stream = require('stream');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  var StringDecoder;
  
  util.inherits(Readable, Stream);
  
  function ReadableState(options, stream) {
    options = options || {};
  
    // the point at which it stops calling _read() to fill the buffer
    // Note: 0 is a valid value, means "don't call _read preemptively ever"
    var hwm = options.highWaterMark;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.buffer = [];
    this.length = 0;
    this.pipes = null;
    this.pipesCount = 0;
    this.flowing = false;
    this.ended = false;
    this.endEmitted = false;
    this.reading = false;
  
    // In streams that never have any data, and do push(null) right away,
    // the consumer can miss the 'end' event if they do some I/O before
    // consuming the stream.  So, we don't emit('end') until some reading
    // happens.
    this.calledRead = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, becuase any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // whenever we return null, then we set a flag to say
    // that we're awaiting a 'readable' event emission.
    this.needReadable = false;
    this.emittedReadable = false;
    this.readableListening = false;
  
  
    // object stream flag. Used to make read(n) ignore n and to
    // make all the buffer merging and length checks go away
    this.objectMode = !!options.objectMode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // when piping, we only care about 'readable' events that happen
    // after read()ing all the bytes and not getting any pushback.
    this.ranOut = false;
  
    // the number of writers that are awaiting a drain event in .pipe()s
    this.awaitDrain = 0;
  
    // if true, a maybeReadMore has been scheduled
    this.readingMore = false;
  
    this.decoder = null;
    this.encoding = null;
    if (options.encoding) {
      if (!StringDecoder)
        StringDecoder = require('string_decoder/').StringDecoder;
      this.decoder = new StringDecoder(options.encoding);
      this.encoding = options.encoding;
    }
  }
  
  function Readable(options) {
    if (!(this instanceof Readable))
      return new Readable(options);
  
    this._readableState = new ReadableState(options, this);
  
    // legacy
    this.readable = true;
  
    Stream.call(this);
  }
  
  // Manually shove something into the read() buffer.
  // This returns true if the highWaterMark has not been hit yet,
  // similar to how Writable.write() returns true if you should
  // write() some more.
  Readable.prototype.push = function(chunk, encoding) {
    var state = this._readableState;
  
    if (typeof chunk === 'string' && !state.objectMode) {
      encoding = encoding || state.defaultEncoding;
      if (encoding !== state.encoding) {
        chunk = new Buffer(chunk, encoding);
        encoding = '';
      }
    }
  
    return readableAddChunk(this, state, chunk, encoding, false);
  };
  
  // Unshift should *always* be something directly out of read()
  Readable.prototype.unshift = function(chunk) {
    var state = this._readableState;
    return readableAddChunk(this, state, chunk, '', true);
  };
  
  function readableAddChunk(stream, state, chunk, encoding, addToFront) {
    var er = chunkInvalid(state, chunk);
    if (er) {
      stream.emit('error', er);
    } else if (chunk === null || chunk === undefined) {
      state.reading = false;
      if (!state.ended)
        onEofChunk(stream, state);
    } else if (state.objectMode || chunk && chunk.length > 0) {
      if (state.ended && !addToFront) {
        var e = new Error('stream.push() after EOF');
        stream.emit('error', e);
      } else if (state.endEmitted && addToFront) {
        var e = new Error('stream.unshift() after end event');
        stream.emit('error', e);
      } else {
        if (state.decoder && !addToFront && !encoding)
          chunk = state.decoder.write(chunk);
  
        // update the buffer info.
        state.length += state.objectMode ? 1 : chunk.length;
        if (addToFront) {
          state.buffer.unshift(chunk);
        } else {
          state.reading = false;
          state.buffer.push(chunk);
        }
  
        if (state.needReadable)
          emitReadable(stream);
  
        maybeReadMore(stream, state);
      }
    } else if (!addToFront) {
      state.reading = false;
    }
  
    return needMoreData(state);
  }
  
  
  
  // if it's past the high water mark, we can push in some more.
  // Also, if we have no data yet, we can stand some
  // more bytes.  This is to work around cases where hwm=0,
  // such as the repl.  Also, if the push() triggered a
  // readable event, and the user called read(largeNumber) such that
  // needReadable was set, then we ought to push more, so that another
  // 'readable' event will be triggered.
  function needMoreData(state) {
    return !state.ended &&
           (state.needReadable ||
            state.length < state.highWaterMark ||
            state.length === 0);
  }
  
  // backwards compatibility.
  Readable.prototype.setEncoding = function(enc) {
    if (!StringDecoder)
      StringDecoder = require('string_decoder/').StringDecoder;
    this._readableState.decoder = new StringDecoder(enc);
    this._readableState.encoding = enc;
  };
  
  // Don't raise the hwm > 128MB
  var MAX_HWM = 0x800000;
  function roundUpToNextPowerOf2(n) {
    if (n >= MAX_HWM) {
      n = MAX_HWM;
    } else {
      // Get the next highest power of 2
      n--;
      for (var p = 1; p < 32; p <<= 1) n |= n >> p;
      n++;
    }
    return n;
  }
  
  function howMuchToRead(n, state) {
    if (state.length === 0 && state.ended)
      return 0;
  
    if (state.objectMode)
      return n === 0 ? 0 : 1;
  
    if (n === null || isNaN(n)) {
      // only flow one buffer at a time
      if (state.flowing && state.buffer.length)
        return state.buffer[0].length;
      else
        return state.length;
    }
  
    if (n <= 0)
      return 0;
  
    // If we're asking for more than the target buffer level,
    // then raise the water mark.  Bump up to the next highest
    // power of 2, to prevent increasing it excessively in tiny
    // amounts.
    if (n > state.highWaterMark)
      state.highWaterMark = roundUpToNextPowerOf2(n);
  
    // don't have that much.  return null, unless we've ended.
    if (n > state.length) {
      if (!state.ended) {
        state.needReadable = true;
        return 0;
      } else
        return state.length;
    }
  
    return n;
  }
  
  // you can override either this method, or the async _read(n) below.
  Readable.prototype.read = function(n) {
    var state = this._readableState;
    state.calledRead = true;
    var nOrig = n;
    var ret;
  
    if (typeof n !== 'number' || n > 0)
      state.emittedReadable = false;
  
    // if we're doing read(0) to trigger a readable event, but we
    // already have a bunch of data in the buffer, then just trigger
    // the 'readable' event and move on.
    if (n === 0 &&
        state.needReadable &&
        (state.length >= state.highWaterMark || state.ended)) {
      emitReadable(this);
      return null;
    }
  
    n = howMuchToRead(n, state);
  
    // if we've ended, and we're now clear, then finish it up.
    if (n === 0 && state.ended) {
      ret = null;
  
      // In cases where the decoder did not receive enough data
      // to produce a full chunk, then immediately received an
      // EOF, state.buffer will contain [<Buffer >, <Buffer 00 ...>].
      // howMuchToRead will see this and coerce the amount to
      // read to zero (because it's looking at the length of the
      // first <Buffer > in state.buffer), and we'll end up here.
      //
      // This can only happen via state.decoder -- no other venue
      // exists for pushing a zero-length chunk into state.buffer
      // and triggering this behavior. In this case, we return our
      // remaining data and end the stream, if appropriate.
      if (state.length > 0 && state.decoder) {
        ret = fromList(n, state);
        state.length -= ret.length;
      }
  
      if (state.length === 0)
        endReadable(this);
  
      return ret;
    }
  
    // All the actual chunk generation logic needs to be
    // *below* the call to _read.  The reason is that in certain
    // synthetic stream cases, such as passthrough streams, _read
    // may be a completely synchronous operation which may change
    // the state of the read buffer, providing enough data when
    // before there was *not* enough.
    //
    // So, the steps are:
    // 1. Figure out what the state of things will be after we do
    // a read from the buffer.
    //
    // 2. If that resulting state will trigger a _read, then call _read.
    // Note that this may be asynchronous, or synchronous.  Yes, it is
    // deeply ugly to write APIs this way, but that still doesn't mean
    // that the Readable class should behave improperly, as streams are
    // designed to be sync/async agnostic.
    // Take note if the _read call is sync or async (ie, if the read call
    // has returned yet), so that we know whether or not it's safe to emit
    // 'readable' etc.
    //
    // 3. Actually pull the requested chunks out of the buffer and return.
  
    // if we need a readable event, then we need to do some reading.
    var doRead = state.needReadable;
  
    // if we currently have less than the highWaterMark, then also read some
    if (state.length - n <= state.highWaterMark)
      doRead = true;
  
    // however, if we've ended, then there's no point, and if we're already
    // reading, then it's unnecessary.
    if (state.ended || state.reading)
      doRead = false;
  
    if (doRead) {
      state.reading = true;
      state.sync = true;
      // if the length is currently zero, then we *need* a readable event.
      if (state.length === 0)
        state.needReadable = true;
      // call internal read method
      this._read(state.highWaterMark);
      state.sync = false;
    }
  
    // If _read called its callback synchronously, then `reading`
    // will be false, and we need to re-evaluate how much data we
    // can return to the user.
    if (doRead && !state.reading)
      n = howMuchToRead(nOrig, state);
  
    if (n > 0)
      ret = fromList(n, state);
    else
      ret = null;
  
    if (ret === null) {
      state.needReadable = true;
      n = 0;
    }
  
    state.length -= n;
  
    // If we have nothing in the buffer, then we want to know
    // as soon as we *do* get something into the buffer.
    if (state.length === 0 && !state.ended)
      state.needReadable = true;
  
    // If we happened to read() exactly the remaining amount in the
    // buffer, and the EOF has been seen at this point, then make sure
    // that we emit 'end' on the very next tick.
    if (state.ended && !state.endEmitted && state.length === 0)
      endReadable(this);
  
    return ret;
  };
  
  function chunkInvalid(state, chunk) {
    var er = null;
    if (!Buffer.isBuffer(chunk) &&
        'string' !== typeof chunk &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      er = new TypeError('Invalid non-string/buffer chunk');
    }
    return er;
  }
  
  
  function onEofChunk(stream, state) {
    if (state.decoder && !state.ended) {
      var chunk = state.decoder.end();
      if (chunk && chunk.length) {
        state.buffer.push(chunk);
        state.length += state.objectMode ? 1 : chunk.length;
      }
    }
    state.ended = true;
  
    // if we've ended and we have some data left, then emit
    // 'readable' now to make sure it gets picked up.
    if (state.length > 0)
      emitReadable(stream);
    else
      endReadable(stream);
  }
  
  // Don't emit readable right away in sync mode, because this can trigger
  // another read() call => stack overflow.  This way, it might trigger
  // a nextTick recursion warning, but that's not so bad.
  function emitReadable(stream) {
    var state = stream._readableState;
    state.needReadable = false;
    if (state.emittedReadable)
      return;
  
    state.emittedReadable = true;
    if (state.sync)
      process.nextTick(function() {
        emitReadable_(stream);
      });
    else
      emitReadable_(stream);
  }
  
  function emitReadable_(stream) {
    stream.emit('readable');
  }
  
  
  // at this point, the user has presumably seen the 'readable' event,
  // and called read() to consume some data.  that may have triggered
  // in turn another _read(n) call, in which case reading = true if
  // it's in progress.
  // However, if we're not ended, or reading, and the length < hwm,
  // then go ahead and try to read some more preemptively.
  function maybeReadMore(stream, state) {
    if (!state.readingMore) {
      state.readingMore = true;
      process.nextTick(function() {
        maybeReadMore_(stream, state);
      });
    }
  }
  
  function maybeReadMore_(stream, state) {
    var len = state.length;
    while (!state.reading && !state.flowing && !state.ended &&
           state.length < state.highWaterMark) {
      stream.read(0);
      if (len === state.length)
        // didn't get any data, stop spinning.
        break;
      else
        len = state.length;
    }
    state.readingMore = false;
  }
  
  // abstract method.  to be overridden in specific implementation classes.
  // call cb(er, data) where data is <= n in length.
  // for virtual (non-string, non-buffer) streams, "length" is somewhat
  // arbitrary, and perhaps not very meaningful.
  Readable.prototype._read = function(n) {
    this.emit('error', new Error('not implemented'));
  };
  
  Readable.prototype.pipe = function(dest, pipeOpts) {
    var src = this;
    var state = this._readableState;
  
    switch (state.pipesCount) {
      case 0:
        state.pipes = dest;
        break;
      case 1:
        state.pipes = [state.pipes, dest];
        break;
      default:
        state.pipes.push(dest);
        break;
    }
    state.pipesCount += 1;
  
    var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
                dest !== process.stdout &&
                dest !== process.stderr;
  
    var endFn = doEnd ? onend : cleanup;
    if (state.endEmitted)
      process.nextTick(endFn);
    else
      src.once('end', endFn);
  
    dest.on('unpipe', onunpipe);
    function onunpipe(readable) {
      if (readable !== src) return;
      cleanup();
    }
  
    function onend() {
      dest.end();
    }
  
    // when the dest drains, it reduces the awaitDrain counter
    // on the source.  This would be more elegant with a .once()
    // handler in flow(), but adding and removing repeatedly is
    // too slow.
    var ondrain = pipeOnDrain(src);
    dest.on('drain', ondrain);
  
    function cleanup() {
      // cleanup event handlers once the pipe is broken
      dest.removeListener('close', onclose);
      dest.removeListener('finish', onfinish);
      dest.removeListener('drain', ondrain);
      dest.removeListener('error', onerror);
      dest.removeListener('unpipe', onunpipe);
      src.removeListener('end', onend);
      src.removeListener('end', cleanup);
  
      // if the reader is waiting for a drain event from this
      // specific writer, then it would cause it to never start
      // flowing again.
      // So, if this is awaiting a drain, then we just call it now.
      // If we don't know, then assume that we are waiting for one.
      if (!dest._writableState || dest._writableState.needDrain)
        ondrain();
    }
  
    // if the dest has an error, then stop piping into it.
    // however, don't suppress the throwing behavior for this.
    function onerror(er) {
      unpipe();
      dest.removeListener('error', onerror);
      if (EE.listenerCount(dest, 'error') === 0)
        dest.emit('error', er);
    }
    // This is a brutally ugly hack to make sure that our error handler
    // is attached before any userland ones.  NEVER DO THIS.
    if (!dest._events || !dest._events.error)
      dest.on('error', onerror);
    else if (isArray(dest._events.error))
      dest._events.error.unshift(onerror);
    else
      dest._events.error = [onerror, dest._events.error];
  
  
  
    // Both close and finish should trigger unpipe, but only once.
    function onclose() {
      dest.removeListener('finish', onfinish);
      unpipe();
    }
    dest.once('close', onclose);
    function onfinish() {
      dest.removeListener('close', onclose);
      unpipe();
    }
    dest.once('finish', onfinish);
  
    function unpipe() {
      src.unpipe(dest);
    }
  
    // tell the dest that it's being piped to
    dest.emit('pipe', src);
  
    // start the flow if it hasn't been started already.
    if (!state.flowing) {
      // the handler that waits for readable events after all
      // the data gets sucked out in flow.
      // This would be easier to follow with a .once() handler
      // in flow(), but that is too slow.
      this.on('readable', pipeOnReadable);
  
      state.flowing = true;
      process.nextTick(function() {
        flow(src);
      });
    }
  
    return dest;
  };
  
  function pipeOnDrain(src) {
    return function() {
      var dest = this;
      var state = src._readableState;
      state.awaitDrain--;
      if (state.awaitDrain === 0)
        flow(src);
    };
  }
  
  function flow(src) {
    var state = src._readableState;
    var chunk;
    state.awaitDrain = 0;
  
    function write(dest, i, list) {
      var written = dest.write(chunk);
      if (false === written) {
        state.awaitDrain++;
      }
    }
  
    while (state.pipesCount && null !== (chunk = src.read())) {
  
      if (state.pipesCount === 1)
        write(state.pipes, 0, null);
      else
        forEach(state.pipes, write);
  
      src.emit('data', chunk);
  
      // if anyone needs a drain, then we have to wait for that.
      if (state.awaitDrain > 0)
        return;
    }
  
    // if every destination was unpiped, either before entering this
    // function, or in the while loop, then stop flowing.
    //
    // NB: This is a pretty rare edge case.
    if (state.pipesCount === 0) {
      state.flowing = false;
  
      // if there were data event listeners added, then switch to old mode.
      if (EE.listenerCount(src, 'data') > 0)
        emitDataEvents(src);
      return;
    }
  
    // at this point, no one needed a drain, so we just ran out of data
    // on the next readable event, start it over again.
    state.ranOut = true;
  }
  
  function pipeOnReadable() {
    if (this._readableState.ranOut) {
      this._readableState.ranOut = false;
      flow(this);
    }
  }
  
  
  Readable.prototype.unpipe = function(dest) {
    var state = this._readableState;
  
    // if we're not piping anywhere, then do nothing.
    if (state.pipesCount === 0)
      return this;
  
    // just one destination.  most common case.
    if (state.pipesCount === 1) {
      // passed in one, but it's not the right one.
      if (dest && dest !== state.pipes)
        return this;
  
      if (!dest)
        dest = state.pipes;
  
      // got a match.
      state.pipes = null;
      state.pipesCount = 0;
      this.removeListener('readable', pipeOnReadable);
      state.flowing = false;
      if (dest)
        dest.emit('unpipe', this);
      return this;
    }
  
    // slow case. multiple pipe destinations.
  
    if (!dest) {
      // remove all.
      var dests = state.pipes;
      var len = state.pipesCount;
      state.pipes = null;
      state.pipesCount = 0;
      this.removeListener('readable', pipeOnReadable);
      state.flowing = false;
  
      for (var i = 0; i < len; i++)
        dests[i].emit('unpipe', this);
      return this;
    }
  
    // try to find the right one.
    var i = indexOf(state.pipes, dest);
    if (i === -1)
      return this;
  
    state.pipes.splice(i, 1);
    state.pipesCount -= 1;
    if (state.pipesCount === 1)
      state.pipes = state.pipes[0];
  
    dest.emit('unpipe', this);
  
    return this;
  };
  
  // set up data events if they are asked for
  // Ensure readable listeners eventually get something
  Readable.prototype.on = function(ev, fn) {
    var res = Stream.prototype.on.call(this, ev, fn);
  
    if (ev === 'data' && !this._readableState.flowing)
      emitDataEvents(this);
  
    if (ev === 'readable' && this.readable) {
      var state = this._readableState;
      if (!state.readableListening) {
        state.readableListening = true;
        state.emittedReadable = false;
        state.needReadable = true;
        if (!state.reading) {
          this.read(0);
        } else if (state.length) {
          emitReadable(this, state);
        }
      }
    }
  
    return res;
  };
  Readable.prototype.addListener = Readable.prototype.on;
  
  // pause() and resume() are remnants of the legacy readable stream API
  // If the user uses them, then switch into old mode.
  Readable.prototype.resume = function() {
    emitDataEvents(this);
    this.read(0);
    this.emit('resume');
  };
  
  Readable.prototype.pause = function() {
    emitDataEvents(this, true);
    this.emit('pause');
  };
  
  function emitDataEvents(stream, startPaused) {
    var state = stream._readableState;
  
    if (state.flowing) {
      // https://github.com/isaacs/readable-stream/issues/16
      throw new Error('Cannot switch to old mode now.');
    }
  
    var paused = startPaused || false;
    var readable = false;
  
    // convert to an old-style stream.
    stream.readable = true;
    stream.pipe = Stream.prototype.pipe;
    stream.on = stream.addListener = Stream.prototype.on;
  
    stream.on('readable', function() {
      readable = true;
  
      var c;
      while (!paused && (null !== (c = stream.read())))
        stream.emit('data', c);
  
      if (c === null) {
        readable = false;
        stream._readableState.needReadable = true;
      }
    });
  
    stream.pause = function() {
      paused = true;
      this.emit('pause');
    };
  
    stream.resume = function() {
      paused = false;
      if (readable)
        process.nextTick(function() {
          stream.emit('readable');
        });
      else
        this.read(0);
      this.emit('resume');
    };
  
    // now make it start, just in case it hadn't already.
    stream.emit('readable');
  }
  
  // wrap an old-style stream as the async data source.
  // This is *not* part of the readable stream interface.
  // It is an ugly unfortunate mess of history.
  Readable.prototype.wrap = function(stream) {
    var state = this._readableState;
    var paused = false;
  
    var self = this;
    stream.on('end', function() {
      if (state.decoder && !state.ended) {
        var chunk = state.decoder.end();
        if (chunk && chunk.length)
          self.push(chunk);
      }
  
      self.push(null);
    });
  
    stream.on('data', function(chunk) {
      if (state.decoder)
        chunk = state.decoder.write(chunk);
  
      // don't skip over falsy values in objectMode
      //if (state.objectMode && util.isNullOrUndefined(chunk))
      if (state.objectMode && (chunk === null || chunk === undefined))
        return;
      else if (!state.objectMode && (!chunk || !chunk.length))
        return;
  
      var ret = self.push(chunk);
      if (!ret) {
        paused = true;
        stream.pause();
      }
    });
  
    // proxy all the other methods.
    // important when wrapping filters and duplexes.
    for (var i in stream) {
      if (typeof stream[i] === 'function' &&
          typeof this[i] === 'undefined') {
        this[i] = function(method) { return function() {
          return stream[method].apply(stream, arguments);
        }}(i);
      }
    }
  
    // proxy certain important events.
    var events = ['error', 'close', 'destroy', 'pause', 'resume'];
    forEach(events, function(ev) {
      stream.on(ev, self.emit.bind(self, ev));
    });
  
    // when we try to consume some more bytes, simply unpause the
    // underlying stream.
    self._read = function(n) {
      if (paused) {
        paused = false;
        stream.resume();
      }
    };
  
    return self;
  };
  
  
  
  // exposed for testing purposes only.
  Readable._fromList = fromList;
  
  // Pluck off n bytes from an array of buffers.
  // Length is the combined lengths of all the buffers in the list.
  function fromList(n, state) {
    var list = state.buffer;
    var length = state.length;
    var stringMode = !!state.decoder;
    var objectMode = !!state.objectMode;
    var ret;
  
    // nothing in the list, definitely empty.
    if (list.length === 0)
      return null;
  
    if (length === 0)
      ret = null;
    else if (objectMode)
      ret = list.shift();
    else if (!n || n >= length) {
      // read it all, truncate the array.
      if (stringMode)
        ret = list.join('');
      else
        ret = Buffer.concat(list, length);
      list.length = 0;
    } else {
      // read just some of it.
      if (n < list[0].length) {
        // just take a part of the first list item.
        // slice is the same for buffers and strings.
        var buf = list[0];
        ret = buf.slice(0, n);
        list[0] = buf.slice(n);
      } else if (n === list[0].length) {
        // first list is a perfect match
        ret = list.shift();
      } else {
        // complex case.
        // we have enough to cover it, but it spans past the first buffer.
        if (stringMode)
          ret = '';
        else
          ret = new Buffer(n);
  
        var c = 0;
        for (var i = 0, l = list.length; i < l && c < n; i++) {
          var buf = list[0];
          var cpy = Math.min(n - c, buf.length);
  
          if (stringMode)
            ret += buf.slice(0, cpy);
          else
            buf.copy(ret, c, 0, cpy);
  
          if (cpy < buf.length)
            list[0] = buf.slice(cpy);
          else
            list.shift();
  
          c += cpy;
        }
      }
    }
  
    return ret;
  }
  
  function endReadable(stream) {
    var state = stream._readableState;
  
    // If we get here before consuming all the bytes, then that is a
    // bug in node.  Should never happen.
    if (state.length > 0)
      throw new Error('endReadable called on non-empty stream');
  
    if (!state.endEmitted && state.calledRead) {
      state.ended = true;
      process.nextTick(function() {
        // Check that we didn't get one last unshift.
        if (!state.endEmitted && state.length === 0) {
          state.endEmitted = true;
          stream.readable = false;
          stream.emit('end');
        }
      });
    }
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  function indexOf (xs, x) {
    for (var i = 0, l = xs.length; i < l; i++) {
      if (xs[i] === x) return i;
    }
    return -1;
  }
  
  }).call(this,require('_process'))
  },{"_process":11,"buffer":12,"core-util-is":43,"events":56,"inherits":194,"isarray":200,"stream":258,"string_decoder/":260}],249:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  
  // a transform stream is a readable/writable stream where you do
  // something with the data.  Sometimes it's called a "filter",
  // but that's not a great name for it, since that implies a thing where
  // some bits pass through, and others are simply ignored.  (That would
  // be a valid example of a transform, of course.)
  //
  // While the output is causally related to the input, it's not a
  // necessarily symmetric or synchronous transformation.  For example,
  // a zlib stream might take multiple plain-text writes(), and then
  // emit a single compressed chunk some time in the future.
  //
  // Here's how this works:
  //
  // The Transform stream has all the aspects of the readable and writable
  // stream classes.  When you write(chunk), that calls _write(chunk,cb)
  // internally, and returns false if there's a lot of pending writes
  // buffered up.  When you call read(), that calls _read(n) until
  // there's enough pending readable data buffered up.
  //
  // In a transform stream, the written data is placed in a buffer.  When
  // _read(n) is called, it transforms the queued up data, calling the
  // buffered _write cb's as it consumes chunks.  If consuming a single
  // written chunk would result in multiple output chunks, then the first
  // outputted bit calls the readcb, and subsequent chunks just go into
  // the read buffer, and will cause it to emit 'readable' if necessary.
  //
  // This way, back-pressure is actually determined by the reading side,
  // since _read has to be called to start processing a new chunk.  However,
  // a pathological inflate type of transform can cause excessive buffering
  // here.  For example, imagine a stream where every byte of input is
  // interpreted as an integer from 0-255, and then results in that many
  // bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
  // 1kb of data being output.  In this case, you could write a very small
  // amount of input, and end up with a very large amount of output.  In
  // such a pathological inflating mechanism, there'd be no way to tell
  // the system to stop doing the transform.  A single 4MB write could
  // cause the system to run out of memory.
  //
  // However, even in such a pathological case, only a single written chunk
  // would be consumed, and then the rest would wait (un-transformed) until
  // the results of the previous transformed chunk were consumed.
  
  module.exports = Transform;
  
  var Duplex = require('./_stream_duplex');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  util.inherits(Transform, Duplex);
  
  
  function TransformState(options, stream) {
    this.afterTransform = function(er, data) {
      return afterTransform(stream, er, data);
    };
  
    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
  }
  
  function afterTransform(stream, er, data) {
    var ts = stream._transformState;
    ts.transforming = false;
  
    var cb = ts.writecb;
  
    if (!cb)
      return stream.emit('error', new Error('no writecb in Transform class'));
  
    ts.writechunk = null;
    ts.writecb = null;
  
    if (data !== null && data !== undefined)
      stream.push(data);
  
    if (cb)
      cb(er);
  
    var rs = stream._readableState;
    rs.reading = false;
    if (rs.needReadable || rs.length < rs.highWaterMark) {
      stream._read(rs.highWaterMark);
    }
  }
  
  
  function Transform(options) {
    if (!(this instanceof Transform))
      return new Transform(options);
  
    Duplex.call(this, options);
  
    var ts = this._transformState = new TransformState(options, this);
  
    // when the writable side finishes, then flush out anything remaining.
    var stream = this;
  
    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
  
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;
  
    this.once('finish', function() {
      if ('function' === typeof this._flush)
        this._flush(function(er) {
          done(stream, er);
        });
      else
        done(stream);
    });
  }
  
  Transform.prototype.push = function(chunk, encoding) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.call(this, chunk, encoding);
  };
  
  // This is the part where you do stuff!
  // override this function in implementation classes.
  // 'chunk' is an input chunk.
  //
  // Call `push(newChunk)` to pass along transformed output
  // to the readable side.  You may call 'push' zero or more times.
  //
  // Call `cb(err)` when you are done with this chunk.  If you pass
  // an error, then that'll put the hurt on the whole operation.  If you
  // never call cb(), then you'll never get another chunk.
  Transform.prototype._transform = function(chunk, encoding, cb) {
    throw new Error('not implemented');
  };
  
  Transform.prototype._write = function(chunk, encoding, cb) {
    var ts = this._transformState;
    ts.writecb = cb;
    ts.writechunk = chunk;
    ts.writeencoding = encoding;
    if (!ts.transforming) {
      var rs = this._readableState;
      if (ts.needTransform ||
          rs.needReadable ||
          rs.length < rs.highWaterMark)
        this._read(rs.highWaterMark);
    }
  };
  
  // Doesn't matter what the args are here.
  // _transform does all the work.
  // That we got here means that the readable side wants more data.
  Transform.prototype._read = function(n) {
    var ts = this._transformState;
  
    if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
      ts.transforming = true;
      this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
    } else {
      // mark that we need a transform, so that any data that comes in
      // will get processed, now that we've asked for it.
      ts.needTransform = true;
    }
  };
  
  
  function done(stream, er) {
    if (er)
      return stream.emit('error', er);
  
    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = stream._writableState;
    var rs = stream._readableState;
    var ts = stream._transformState;
  
    if (ws.length)
      throw new Error('calling transform done when ws.length != 0');
  
    if (ts.transforming)
      throw new Error('calling transform done when still transforming');
  
    return stream.push(null);
  }
  
  },{"./_stream_duplex":246,"core-util-is":43,"inherits":194}],250:[function(require,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // A bit simpler than readable streams.
  // Implement an async ._write(chunk, cb), and it'll handle all
  // the drain event emission and buffering.
  
  module.exports = Writable;
  
  /*<replacement>*/
  var Buffer = require('buffer').Buffer;
  /*</replacement>*/
  
  Writable.WritableState = WritableState;
  
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  var Stream = require('stream');
  
  util.inherits(Writable, Stream);
  
  function WriteReq(chunk, encoding, cb) {
    this.chunk = chunk;
    this.encoding = encoding;
    this.callback = cb;
  }
  
  function WritableState(options, stream) {
    options = options || {};
  
    // the point at which write() starts returning false
    // Note: 0 is a valid value, means that we always return false if
    // the entire buffer is not flushed immediately on write()
    var hwm = options.highWaterMark;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
  
    // object stream flag to indicate whether or not this stream
    // contains buffers or objects.
    this.objectMode = !!options.objectMode;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.needDrain = false;
    // at the start of calling end()
    this.ending = false;
    // when end() has been called, and returned
    this.ended = false;
    // when 'finish' is emitted
    this.finished = false;
  
    // should we decode strings into buffers before passing to _write?
    // this is here so that some node-core streams can optimize string
    // handling at a lower level.
    var noDecode = options.decodeStrings === false;
    this.decodeStrings = !noDecode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // not an actual buffer we keep track of, but a measurement
    // of how much we're waiting to get pushed to some underlying
    // socket or file.
    this.length = 0;
  
    // a flag to see when we're in the middle of a write.
    this.writing = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, becuase any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // a flag to know if we're processing previously buffered items, which
    // may call the _write() callback in the same tick, so that we don't
    // end up in an overlapped onwrite situation.
    this.bufferProcessing = false;
  
    // the callback that's passed to _write(chunk,cb)
    this.onwrite = function(er) {
      onwrite(stream, er);
    };
  
    // the callback that the user supplies to write(chunk,encoding,cb)
    this.writecb = null;
  
    // the amount that is being written when _write is called.
    this.writelen = 0;
  
    this.buffer = [];
  
    // True if the error was already emitted and should not be thrown again
    this.errorEmitted = false;
  }
  
  function Writable(options) {
    var Duplex = require('./_stream_duplex');
  
    // Writable ctor is applied to Duplexes, though they're not
    // instanceof Writable, they're instanceof Readable.
    if (!(this instanceof Writable) && !(this instanceof Duplex))
      return new Writable(options);
  
    this._writableState = new WritableState(options, this);
  
    // legacy.
    this.writable = true;
  
    Stream.call(this);
  }
  
  // Otherwise people can pipe Writable streams, which is just wrong.
  Writable.prototype.pipe = function() {
    this.emit('error', new Error('Cannot pipe. Not readable.'));
  };
  
  
  function writeAfterEnd(stream, state, cb) {
    var er = new Error('write after end');
    // TODO: defer error events consistently everywhere, not just the cb
    stream.emit('error', er);
    process.nextTick(function() {
      cb(er);
    });
  }
  
  // If we get something that is not a buffer, string, null, or undefined,
  // and we're not in objectMode, then that's an error.
  // Otherwise stream chunks are all considered to be of length=1, and the
  // watermarks determine how many objects to keep in the buffer, rather than
  // how many bytes or characters.
  function validChunk(stream, state, chunk, cb) {
    var valid = true;
    if (!Buffer.isBuffer(chunk) &&
        'string' !== typeof chunk &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      var er = new TypeError('Invalid non-string/buffer chunk');
      stream.emit('error', er);
      process.nextTick(function() {
        cb(er);
      });
      valid = false;
    }
    return valid;
  }
  
  Writable.prototype.write = function(chunk, encoding, cb) {
    var state = this._writableState;
    var ret = false;
  
    if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    else if (!encoding)
      encoding = state.defaultEncoding;
  
    if (typeof cb !== 'function')
      cb = function() {};
  
    if (state.ended)
      writeAfterEnd(this, state, cb);
    else if (validChunk(this, state, chunk, cb))
      ret = writeOrBuffer(this, state, chunk, encoding, cb);
  
    return ret;
  };
  
  function decodeChunk(state, chunk, encoding) {
    if (!state.objectMode &&
        state.decodeStrings !== false &&
        typeof chunk === 'string') {
      chunk = new Buffer(chunk, encoding);
    }
    return chunk;
  }
  
  // if we're already writing something, then just put this
  // in the queue, and wait our turn.  Otherwise, call _write
  // If we return false, then we need a drain event, so set that flag.
  function writeOrBuffer(stream, state, chunk, encoding, cb) {
    chunk = decodeChunk(state, chunk, encoding);
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    var len = state.objectMode ? 1 : chunk.length;
  
    state.length += len;
  
    var ret = state.length < state.highWaterMark;
    // we must ensure that previous needDrain will not be reset to false.
    if (!ret)
      state.needDrain = true;
  
    if (state.writing)
      state.buffer.push(new WriteReq(chunk, encoding, cb));
    else
      doWrite(stream, state, len, chunk, encoding, cb);
  
    return ret;
  }
  
  function doWrite(stream, state, len, chunk, encoding, cb) {
    state.writelen = len;
    state.writecb = cb;
    state.writing = true;
    state.sync = true;
    stream._write(chunk, encoding, state.onwrite);
    state.sync = false;
  }
  
  function onwriteError(stream, state, sync, er, cb) {
    if (sync)
      process.nextTick(function() {
        cb(er);
      });
    else
      cb(er);
  
    stream._writableState.errorEmitted = true;
    stream.emit('error', er);
  }
  
  function onwriteStateUpdate(state) {
    state.writing = false;
    state.writecb = null;
    state.length -= state.writelen;
    state.writelen = 0;
  }
  
  function onwrite(stream, er) {
    var state = stream._writableState;
    var sync = state.sync;
    var cb = state.writecb;
  
    onwriteStateUpdate(state);
  
    if (er)
      onwriteError(stream, state, sync, er, cb);
    else {
      // Check if we're actually ready to finish, but don't emit yet
      var finished = needFinish(stream, state);
  
      if (!finished && !state.bufferProcessing && state.buffer.length)
        clearBuffer(stream, state);
  
      if (sync) {
        process.nextTick(function() {
          afterWrite(stream, state, finished, cb);
        });
      } else {
        afterWrite(stream, state, finished, cb);
      }
    }
  }
  
  function afterWrite(stream, state, finished, cb) {
    if (!finished)
      onwriteDrain(stream, state);
    cb();
    if (finished)
      finishMaybe(stream, state);
  }
  
  // Must force callback to be called on nextTick, so that we don't
  // emit 'drain' before the write() consumer gets the 'false' return
  // value, and has a chance to attach a 'drain' listener.
  function onwriteDrain(stream, state) {
    if (state.length === 0 && state.needDrain) {
      state.needDrain = false;
      stream.emit('drain');
    }
  }
  
  
  // if there's something in the buffer waiting, then process it
  function clearBuffer(stream, state) {
    state.bufferProcessing = true;
  
    for (var c = 0; c < state.buffer.length; c++) {
      var entry = state.buffer[c];
      var chunk = entry.chunk;
      var encoding = entry.encoding;
      var cb = entry.callback;
      var len = state.objectMode ? 1 : chunk.length;
  
      doWrite(stream, state, len, chunk, encoding, cb);
  
      // if we didn't call the onwrite immediately, then
      // it means that we need to wait until it does.
      // also, that means that the chunk and cb are currently
      // being processed, so move the buffer counter past them.
      if (state.writing) {
        c++;
        break;
      }
    }
  
    state.bufferProcessing = false;
    if (c < state.buffer.length)
      state.buffer = state.buffer.slice(c);
    else
      state.buffer.length = 0;
  }
  
  Writable.prototype._write = function(chunk, encoding, cb) {
    cb(new Error('not implemented'));
  };
  
  Writable.prototype.end = function(chunk, encoding, cb) {
    var state = this._writableState;
  
    if (typeof chunk === 'function') {
      cb = chunk;
      chunk = null;
      encoding = null;
    } else if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (typeof chunk !== 'undefined' && chunk !== null)
      this.write(chunk, encoding);
  
    // ignore unnecessary end() calls.
    if (!state.ending && !state.finished)
      endWritable(this, state, cb);
  };
  
  
  function needFinish(stream, state) {
    return (state.ending &&
            state.length === 0 &&
            !state.finished &&
            !state.writing);
  }
  
  function finishMaybe(stream, state) {
    var need = needFinish(stream, state);
    if (need) {
      state.finished = true;
      stream.emit('finish');
    }
    return need;
  }
  
  function endWritable(stream, state, cb) {
    state.ending = true;
    finishMaybe(stream, state);
    if (cb) {
      if (state.finished)
        process.nextTick(cb);
      else
        stream.once('finish', cb);
    }
    state.ended = true;
  }
  
  }).call(this,require('_process'))
  },{"./_stream_duplex":246,"_process":11,"buffer":12,"core-util-is":43,"inherits":194,"stream":258}],251:[function(require,module,exports){
  module.exports = require("./lib/_stream_passthrough.js")
  
  },{"./lib/_stream_passthrough.js":247}],252:[function(require,module,exports){
  var Stream = require('stream'); // hack to fix a circular dependency issue when used with browserify
  exports = module.exports = require('./lib/_stream_readable.js');
  exports.Stream = Stream;
  exports.Readable = exports;
  exports.Writable = require('./lib/_stream_writable.js');
  exports.Duplex = require('./lib/_stream_duplex.js');
  exports.Transform = require('./lib/_stream_transform.js');
  exports.PassThrough = require('./lib/_stream_passthrough.js');
  
  },{"./lib/_stream_duplex.js":246,"./lib/_stream_passthrough.js":247,"./lib/_stream_readable.js":248,"./lib/_stream_transform.js":249,"./lib/_stream_writable.js":250,"stream":258}],253:[function(require,module,exports){
  module.exports = require("./lib/_stream_transform.js")
  
  },{"./lib/_stream_transform.js":249}],254:[function(require,module,exports){
  module.exports = require("./lib/_stream_writable.js")
  
  },{"./lib/_stream_writable.js":250}],255:[function(require,module,exports){
  /*!
   * repeat-string <https://github.com/jonschlinkert/repeat-string>
   *
   * Copyright (c) 2014-2015, Jon Schlinkert.
   * Licensed under the MIT License.
   */
  
  'use strict';
  
  /**
   * Expose `repeat`
   */
  
  module.exports = repeat;
  
  /**
   * Repeat the given `string` the specified `number`
   * of times.
   *
   * **Example:**
   *
   * ```js
   * var repeat = require('repeat-string');
   * repeat('A', 5);
   * //=> AAAAA
   * ```
   *
   * @param {String} `string` The string to repeat
   * @param {Number} `number` The number of times to repeat the string
   * @return {String} Repeated string
   * @api public
   */
  
  function repeat(str, num) {
    if (typeof str !== 'string') {
      throw new TypeError('repeat-string expects a string.');
    }
  
    if (num === 1) return str;
    if (num === 2) return str + str;
  
    var max = str.length * num;
    if (cache !== str || typeof cache === 'undefined') {
      cache = str;
      res = '';
    }
  
    while (max > res.length && num > 0) {
      if (num & 1) {
        res += str;
      }
  
      num >>= 1;
      if (!num) break;
      str += str;
    }
  
    return res.substr(0, max);
  }
  
  /**
   * Results cache
   */
  
  var res = '';
  var cache;
  
  },{}],256:[function(require,module,exports){
  //filter will reemit the data if cb(err,pass) pass is truthy
  
  // reduce is more tricky
  // maybe we want to group the reductions or emit progress updates occasionally
  // the most basic reduce just emits one 'data' event after it has recieved 'end'
  
  
  var through = require('through')
  var Decoder = require('string_decoder').StringDecoder
  
  module.exports = split
  
  //TODO pass in a function to map across the lines.
  
  function split (matcher, mapper, options) {
    var decoder = new Decoder()
    var soFar = ''
    var maxLength = options && options.maxLength;
    if('function' === typeof matcher)
      mapper = matcher, matcher = null
    if (!matcher)
      matcher = /\r?\n/
  
    function emit(stream, piece) {
      if(mapper) {
        try {
          piece = mapper(piece)
        }
        catch (err) {
          return stream.emit('error', err)
        }
        if('undefined' !== typeof piece)
          stream.queue(piece)
      }
      else
        stream.queue(piece)
    }
  
    function next (stream, buffer) {
      var pieces = ((soFar != null ? soFar : '') + buffer).split(matcher)
      soFar = pieces.pop()
  
      if (maxLength && soFar.length > maxLength)
        stream.emit('error', new Error('maximum buffer reached'))
  
      for (var i = 0; i < pieces.length; i++) {
        var piece = pieces[i]
        emit(stream, piece)
      }
    }
  
    return through(function (b) {
      next(this, decoder.write(b))
    },
    function () {
      if(decoder.end)
        next(this, decoder.end())
      if(soFar != null)
        emit(this, soFar)
      this.queue(null)
    })
  }
  
  
  },{"string_decoder":260,"through":261}],257:[function(require,module,exports){
  (function(window) {
      var re = {
          not_string: /[^s]/,
          number: /[diefg]/,
          json: /[j]/,
          not_json: /[^j]/,
          text: /^[^\x25]+/,
          modulo: /^\x25{2}/,
          placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijosuxX])/,
          key: /^([a-z_][a-z_\d]*)/i,
          key_access: /^\.([a-z_][a-z_\d]*)/i,
          index_access: /^\[(\d+)\]/,
          sign: /^[\+\-]/
      }
  
      function sprintf() {
          var key = arguments[0], cache = sprintf.cache
          if (!(cache[key] && cache.hasOwnProperty(key))) {
              cache[key] = sprintf.parse(key)
          }
          return sprintf.format.call(null, cache[key], arguments)
      }
  
      sprintf.format = function(parse_tree, argv) {
          var cursor = 1, tree_length = parse_tree.length, node_type = "", arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = ""
          for (i = 0; i < tree_length; i++) {
              node_type = get_type(parse_tree[i])
              if (node_type === "string") {
                  output[output.length] = parse_tree[i]
              }
              else if (node_type === "array") {
                  match = parse_tree[i] // convenience purposes only
                  if (match[2]) { // keyword argument
                      arg = argv[cursor]
                      for (k = 0; k < match[2].length; k++) {
                          if (!arg.hasOwnProperty(match[2][k])) {
                              throw new Error(sprintf("[sprintf] property '%s' does not exist", match[2][k]))
                          }
                          arg = arg[match[2][k]]
                      }
                  }
                  else if (match[1]) { // positional argument (explicit)
                      arg = argv[match[1]]
                  }
                  else { // positional argument (implicit)
                      arg = argv[cursor++]
                  }
  
                  if (get_type(arg) == "function") {
                      arg = arg()
                  }
  
                  if (re.not_string.test(match[8]) && re.not_json.test(match[8]) && (get_type(arg) != "number" && isNaN(arg))) {
                      throw new TypeError(sprintf("[sprintf] expecting number but found %s", get_type(arg)))
                  }
  
                  if (re.number.test(match[8])) {
                      is_positive = arg >= 0
                  }
  
                  switch (match[8]) {
                      case "b":
                          arg = arg.toString(2)
                      break
                      case "c":
                          arg = String.fromCharCode(arg)
                      break
                      case "d":
                      case "i":
                          arg = parseInt(arg, 10)
                      break
                      case "j":
                          arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0)
                      break
                      case "e":
                          arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential()
                      break
                      case "f":
                          arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg)
                      break
                      case "g":
                          arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg)
                      break
                      case "o":
                          arg = arg.toString(8)
                      break
                      case "s":
                          arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg)
                      break
                      case "u":
                          arg = arg >>> 0
                      break
                      case "x":
                          arg = arg.toString(16)
                      break
                      case "X":
                          arg = arg.toString(16).toUpperCase()
                      break
                  }
                  if (re.json.test(match[8])) {
                      output[output.length] = arg
                  }
                  else {
                      if (re.number.test(match[8]) && (!is_positive || match[3])) {
                          sign = is_positive ? "+" : "-"
                          arg = arg.toString().replace(re.sign, "")
                      }
                      else {
                          sign = ""
                      }
                      pad_character = match[4] ? match[4] === "0" ? "0" : match[4].charAt(1) : " "
                      pad_length = match[6] - (sign + arg).length
                      pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : "") : ""
                      output[output.length] = match[5] ? sign + arg + pad : (pad_character === "0" ? sign + pad + arg : pad + sign + arg)
                  }
              }
          }
          return output.join("")
      }
  
      sprintf.cache = {}
  
      sprintf.parse = function(fmt) {
          var _fmt = fmt, match = [], parse_tree = [], arg_names = 0
          while (_fmt) {
              if ((match = re.text.exec(_fmt)) !== null) {
                  parse_tree[parse_tree.length] = match[0]
              }
              else if ((match = re.modulo.exec(_fmt)) !== null) {
                  parse_tree[parse_tree.length] = "%"
              }
              else if ((match = re.placeholder.exec(_fmt)) !== null) {
                  if (match[2]) {
                      arg_names |= 1
                      var field_list = [], replacement_field = match[2], field_match = []
                      if ((field_match = re.key.exec(replacement_field)) !== null) {
                          field_list[field_list.length] = field_match[1]
                          while ((replacement_field = replacement_field.substring(field_match[0].length)) !== "") {
                              if ((field_match = re.key_access.exec(replacement_field)) !== null) {
                                  field_list[field_list.length] = field_match[1]
                              }
                              else if ((field_match = re.index_access.exec(replacement_field)) !== null) {
                                  field_list[field_list.length] = field_match[1]
                              }
                              else {
                                  throw new SyntaxError("[sprintf] failed to parse named argument key")
                              }
                          }
                      }
                      else {
                          throw new SyntaxError("[sprintf] failed to parse named argument key")
                      }
                      match[2] = field_list
                  }
                  else {
                      arg_names |= 2
                  }
                  if (arg_names === 3) {
                      throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported")
                  }
                  parse_tree[parse_tree.length] = match
              }
              else {
                  throw new SyntaxError("[sprintf] unexpected placeholder")
              }
              _fmt = _fmt.substring(match[0].length)
          }
          return parse_tree
      }
  
      var vsprintf = function(fmt, argv, _argv) {
          _argv = (argv || []).slice(0)
          _argv.splice(0, 0, fmt)
          return sprintf.apply(null, _argv)
      }
  
      /**
       * helpers
       */
      function get_type(variable) {
          return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase()
      }
  
      function str_repeat(input, multiplier) {
          return Array(multiplier + 1).join(input)
      }
  
      /**
       * export to either browser or node.js
       */
      if (typeof exports !== "undefined") {
          exports.sprintf = sprintf
          exports.vsprintf = vsprintf
      }
      else {
          window.sprintf = sprintf
          window.vsprintf = vsprintf
  
          if (typeof define === "function" && define.amd) {
              define(function() {
                  return {
                      sprintf: sprintf,
                      vsprintf: vsprintf
                  }
              })
          }
      }
  })(typeof window === "undefined" ? this : window);
  
  },{}],258:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  module.exports = Stream;
  
  var EE = require('events').EventEmitter;
  var inherits = require('inherits');
  
  inherits(Stream, EE);
  Stream.Readable = require('readable-stream/readable.js');
  Stream.Writable = require('readable-stream/writable.js');
  Stream.Duplex = require('readable-stream/duplex.js');
  Stream.Transform = require('readable-stream/transform.js');
  Stream.PassThrough = require('readable-stream/passthrough.js');
  
  // Backwards-compat with node 0.4.x
  Stream.Stream = Stream;
  
  
  
  // old-style streams.  Note that the pipe method (the only relevant
  // part of this class) is overridden in the Readable class.
  
  function Stream() {
    EE.call(this);
  }
  
  Stream.prototype.pipe = function(dest, options) {
    var source = this;
  
    function ondata(chunk) {
      if (dest.writable) {
        if (false === dest.write(chunk) && source.pause) {
          source.pause();
        }
      }
    }
  
    source.on('data', ondata);
  
    function ondrain() {
      if (source.readable && source.resume) {
        source.resume();
      }
    }
  
    dest.on('drain', ondrain);
  
    // If the 'end' option is not supplied, dest.end() will be called when
    // source gets the 'end' or 'close' events.  Only dest.end() once.
    if (!dest._isStdio && (!options || options.end !== false)) {
      source.on('end', onend);
      source.on('close', onclose);
    }
  
    var didOnEnd = false;
    function onend() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      dest.end();
    }
  
  
    function onclose() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      if (typeof dest.destroy === 'function') dest.destroy();
    }
  
    // don't leave dangling pipes when there are errors.
    function onerror(er) {
      cleanup();
      if (EE.listenerCount(this, 'error') === 0) {
        throw er; // Unhandled stream error in pipe.
      }
    }
  
    source.on('error', onerror);
    dest.on('error', onerror);
  
    // remove all the event listeners that were added.
    function cleanup() {
      source.removeListener('data', ondata);
      dest.removeListener('drain', ondrain);
  
      source.removeListener('end', onend);
      source.removeListener('close', onclose);
  
      source.removeListener('error', onerror);
      dest.removeListener('error', onerror);
  
      source.removeListener('end', cleanup);
      source.removeListener('close', cleanup);
  
      dest.removeListener('close', cleanup);
    }
  
    source.on('end', cleanup);
    source.on('close', cleanup);
  
    dest.on('close', cleanup);
  
    dest.emit('pipe', source);
  
    // Allow for unix-like usage: A.pipe(B).pipe(C)
    return dest;
  };
  
  },{"events":56,"inherits":194,"readable-stream/duplex.js":245,"readable-stream/passthrough.js":251,"readable-stream/readable.js":252,"readable-stream/transform.js":253,"readable-stream/writable.js":254}],259:[function(require,module,exports){
  'use strict';
  module.exports = function (str) {
  	return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
  		return '%' + c.charCodeAt(0).toString(16);
  	});
  };
  
  },{}],260:[function(require,module,exports){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  var Buffer = require('buffer').Buffer;
  
  var isBufferEncoding = Buffer.isEncoding
    || function(encoding) {
         switch (encoding && encoding.toLowerCase()) {
           case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
           default: return false;
         }
       }
  
  
  function assertEncoding(encoding) {
    if (encoding && !isBufferEncoding(encoding)) {
      throw new Error('Unknown encoding: ' + encoding);
    }
  }
  
  // StringDecoder provides an interface for efficiently splitting a series of
  // buffers into a series of JS strings without breaking apart multi-byte
  // characters. CESU-8 is handled as part of the UTF-8 encoding.
  //
  // @TODO Handling all encodings inside a single object makes it very difficult
  // to reason about this code, so it should be split up in the future.
  // @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
  // points as used by CESU-8.
  var StringDecoder = exports.StringDecoder = function(encoding) {
    this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
    assertEncoding(encoding);
    switch (this.encoding) {
      case 'utf8':
        // CESU-8 represents each of Surrogate Pair by 3-bytes
        this.surrogateSize = 3;
        break;
      case 'ucs2':
      case 'utf16le':
        // UTF-16 represents each of Surrogate Pair by 2-bytes
        this.surrogateSize = 2;
        this.detectIncompleteChar = utf16DetectIncompleteChar;
        break;
      case 'base64':
        // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
        this.surrogateSize = 3;
        this.detectIncompleteChar = base64DetectIncompleteChar;
        break;
      default:
        this.write = passThroughWrite;
        return;
    }
  
    // Enough space to store all bytes of a single character. UTF-8 needs 4
    // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
    this.charBuffer = new Buffer(6);
    // Number of bytes received for the current incomplete multi-byte character.
    this.charReceived = 0;
    // Number of bytes expected for the current incomplete multi-byte character.
    this.charLength = 0;
  };
  
  
  // write decodes the given buffer and returns it as JS string that is
  // guaranteed to not contain any partial multi-byte characters. Any partial
  // character found at the end of the buffer is buffered up, and will be
  // returned when calling write again with the remaining bytes.
  //
  // Note: Converting a Buffer containing an orphan surrogate to a String
  // currently works, but converting a String to a Buffer (via `new Buffer`, or
  // Buffer#write) will replace incomplete surrogates with the unicode
  // replacement character. See https://codereview.chromium.org/121173009/ .
  StringDecoder.prototype.write = function(buffer) {
    var charStr = '';
    // if our last write ended with an incomplete multibyte character
    while (this.charLength) {
      // determine how many remaining bytes this buffer has to offer for this char
      var available = (buffer.length >= this.charLength - this.charReceived) ?
          this.charLength - this.charReceived :
          buffer.length;
  
      // add the new bytes to the char buffer
      buffer.copy(this.charBuffer, this.charReceived, 0, available);
      this.charReceived += available;
  
      if (this.charReceived < this.charLength) {
        // still not enough chars in this buffer? wait for more ...
        return '';
      }
  
      // remove bytes belonging to the current character from the buffer
      buffer = buffer.slice(available, buffer.length);
  
      // get the character that was split
      charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
  
      // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
      var charCode = charStr.charCodeAt(charStr.length - 1);
      if (charCode >= 0xD800 && charCode <= 0xDBFF) {
        this.charLength += this.surrogateSize;
        charStr = '';
        continue;
      }
      this.charReceived = this.charLength = 0;
  
      // if there are no more bytes in this buffer, just emit our char
      if (buffer.length === 0) {
        return charStr;
      }
      break;
    }
  
    // determine and set charLength / charReceived
    this.detectIncompleteChar(buffer);
  
    var end = buffer.length;
    if (this.charLength) {
      // buffer the incomplete character bytes we got
      buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
      end -= this.charReceived;
    }
  
    charStr += buffer.toString(this.encoding, 0, end);
  
    var end = charStr.length - 1;
    var charCode = charStr.charCodeAt(end);
    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
      var size = this.surrogateSize;
      this.charLength += size;
      this.charReceived += size;
      this.charBuffer.copy(this.charBuffer, size, 0, size);
      buffer.copy(this.charBuffer, 0, 0, size);
      return charStr.substring(0, end);
    }
  
    // or just emit the charStr
    return charStr;
  };
  
  // detectIncompleteChar determines if there is an incomplete UTF-8 character at
  // the end of the given buffer. If so, it sets this.charLength to the byte
  // length that character, and sets this.charReceived to the number of bytes
  // that are available for this character.
  StringDecoder.prototype.detectIncompleteChar = function(buffer) {
    // determine how many bytes we have to check at the end of this buffer
    var i = (buffer.length >= 3) ? 3 : buffer.length;
  
    // Figure out if one of the last i bytes of our buffer announces an
    // incomplete char.
    for (; i > 0; i--) {
      var c = buffer[buffer.length - i];
  
      // See http://en.wikipedia.org/wiki/UTF-8#Description
  
      // 110XXXXX
      if (i == 1 && c >> 5 == 0x06) {
        this.charLength = 2;
        break;
      }
  
      // 1110XXXX
      if (i <= 2 && c >> 4 == 0x0E) {
        this.charLength = 3;
        break;
      }
  
      // 11110XXX
      if (i <= 3 && c >> 3 == 0x1E) {
        this.charLength = 4;
        break;
      }
    }
    this.charReceived = i;
  };
  
  StringDecoder.prototype.end = function(buffer) {
    var res = '';
    if (buffer && buffer.length)
      res = this.write(buffer);
  
    if (this.charReceived) {
      var cr = this.charReceived;
      var buf = this.charBuffer;
      var enc = this.encoding;
      res += buf.slice(0, cr).toString(enc);
    }
  
    return res;
  };
  
  function passThroughWrite(buffer) {
    return buffer.toString(this.encoding);
  }
  
  function utf16DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 2;
    this.charLength = this.charReceived ? 2 : 0;
  }
  
  function base64DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 3;
    this.charLength = this.charReceived ? 3 : 0;
  }
  
  },{"buffer":12}],261:[function(require,module,exports){
  (function (process){
  var Stream = require('stream')
  
  // through
  //
  // a stream that does nothing but re-emit the input.
  // useful for aggregating a series of changing but not ending streams into one stream)
  
  exports = module.exports = through
  through.through = through
  
  //create a readable writable stream.
  
  function through (write, end, opts) {
    write = write || function (data) { this.queue(data) }
    end = end || function () { this.queue(null) }
  
    var ended = false, destroyed = false, buffer = [], _ended = false
    var stream = new Stream()
    stream.readable = stream.writable = true
    stream.paused = false
  
  //  stream.autoPause   = !(opts && opts.autoPause   === false)
    stream.autoDestroy = !(opts && opts.autoDestroy === false)
  
    stream.write = function (data) {
      write.call(this, data)
      return !stream.paused
    }
  
    function drain() {
      while(buffer.length && !stream.paused) {
        var data = buffer.shift()
        if(null === data)
          return stream.emit('end')
        else
          stream.emit('data', data)
      }
    }
  
    stream.queue = stream.push = function (data) {
  //    console.error(ended)
      if(_ended) return stream
      if(data === null) _ended = true
      buffer.push(data)
      drain()
      return stream
    }
  
    //this will be registered as the first 'end' listener
    //must call destroy next tick, to make sure we're after any
    //stream piped from here.
    //this is only a problem if end is not emitted synchronously.
    //a nicer way to do this is to make sure this is the last listener for 'end'
  
    stream.on('end', function () {
      stream.readable = false
      if(!stream.writable && stream.autoDestroy)
        process.nextTick(function () {
          stream.destroy()
        })
    })
  
    function _end () {
      stream.writable = false
      end.call(stream)
      if(!stream.readable && stream.autoDestroy)
        stream.destroy()
    }
  
    stream.end = function (data) {
      if(ended) return
      ended = true
      if(arguments.length) stream.write(data)
      _end() // will emit or queue
      return stream
    }
  
    stream.destroy = function () {
      if(destroyed) return
      destroyed = true
      ended = true
      buffer.length = 0
      stream.writable = stream.readable = false
      stream.emit('close')
      return stream
    }
  
    stream.pause = function () {
      if(stream.paused) return
      stream.paused = true
      return stream
    }
  
    stream.resume = function () {
      if(stream.paused) {
        stream.paused = false
        stream.emit('resume')
      }
      drain()
      //may have become paused again,
      //as drain emits 'data'.
      if(!stream.paused)
        stream.emit('drain')
      return stream
    }
    return stream
  }
  
  
  }).call(this,require('_process'))
  },{"_process":11,"stream":258}],262:[function(require,module,exports){
  
  exports = module.exports = trim;
  
  function trim(str){
    return str.replace(/^\s*|\s*$/g, '');
  }
  
  exports.left = function(str){
    return str.replace(/^\s*/, '');
  };
  
  exports.right = function(str){
    return str.replace(/\s*$/, '');
  };
  
  },{}],263:[function(require,module,exports){
  arguments[4][49][0].apply(exports,arguments)
  },{"./lib/type":264,"C:\\Users\\Olivier\\Projets\\LD34\\PostLD34\\git\\LD34\\node_modules\\deep-eql\\node_modules\\type-detect\\index.js":49}],264:[function(require,module,exports){
  /*!
   * type-detect
   * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
   * MIT Licensed
   */
  
  /*!
   * Primary Exports
   */
  
  var exports = module.exports = getType;
  
  /**
   * ### typeOf (obj)
   *
   * Use several different techniques to determine
   * the type of object being tested.
   *
   *
   * @param {Mixed} object
   * @return {String} object type
   * @api public
   */
  var objectTypeRegexp = /^\[object (.*)\]$/;
  
  function getType(obj) {
    var type = Object.prototype.toString.call(obj).match(objectTypeRegexp)[1].toLowerCase();
    // Let "new String('')" return 'object'
    if (typeof Promise === 'function' && obj instanceof Promise) return 'promise';
    // PhantomJS has type "DOMWindow" for null
    if (obj === null) return 'null';
    // PhantomJS has type "DOMWindow" for undefined
    if (obj === undefined) return 'undefined';
    return type;
  }
  
  exports.Library = Library;
  
  /**
   * ### Library
   *
   * Create a repository for custom type detection.
   *
   * ```js
   * var lib = new type.Library;
   * ```
   *
   */
  
  function Library() {
    if (!(this instanceof Library)) return new Library();
    this.tests = {};
  }
  
  /**
   * #### .of (obj)
   *
   * Expose replacement `typeof` detection to the library.
   *
   * ```js
   * if ('string' === lib.of('hello world')) {
   *   // ...
   * }
   * ```
   *
   * @param {Mixed} object to test
   * @return {String} type
   */
  
  Library.prototype.of = getType;
  
  /**
   * #### .define (type, test)
   *
   * Add a test to for the `.test()` assertion.
   *
   * Can be defined as a regular expression:
   *
   * ```js
   * lib.define('int', /^[0-9]+$/);
   * ```
   *
   * ... or as a function:
   *
   * ```js
   * lib.define('bln', function (obj) {
   *   if ('boolean' === lib.of(obj)) return true;
   *   var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
   *   if ('string' === lib.of(obj)) obj = obj.toLowerCase();
   *   return !! ~blns.indexOf(obj);
   * });
   * ```
   *
   * @param {String} type
   * @param {RegExp|Function} test
   * @api public
   */
  
  Library.prototype.define = function(type, test) {
    if (arguments.length === 1) return this.tests[type];
    this.tests[type] = test;
    return this;
  };
  
  /**
   * #### .test (obj, test)
   *
   * Assert that an object is of type. Will first
   * check natives, and if that does not pass it will
   * use the user defined custom tests.
   *
   * ```js
   * assert(lib.test('1', 'int'));
   * assert(lib.test('yes', 'bln'));
   * ```
   *
   * @param {Mixed} object
   * @param {String} type
   * @return {Boolean} result
   * @api public
   */
  
  Library.prototype.test = function(obj, type) {
    if (type === getType(obj)) return true;
    var test = this.tests[type];
  
    if (test && 'regexp' === getType(test)) {
      return test.test(obj);
    } else if (test && 'function' === getType(test)) {
      return test(obj);
    } else {
      throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
    }
  };
  
  },{}],265:[function(require,module,exports){
  (function (global,Buffer){
  'use strict'
  
  var bits = require('bit-twiddle')
  var dup = require('dup')
  
  //Legacy pool support
  if(!global.__TYPEDARRAY_POOL) {
    global.__TYPEDARRAY_POOL = {
        UINT8   : dup([32, 0])
      , UINT16  : dup([32, 0])
      , UINT32  : dup([32, 0])
      , INT8    : dup([32, 0])
      , INT16   : dup([32, 0])
      , INT32   : dup([32, 0])
      , FLOAT   : dup([32, 0])
      , DOUBLE  : dup([32, 0])
      , DATA    : dup([32, 0])
      , UINT8C  : dup([32, 0])
      , BUFFER  : dup([32, 0])
    }
  }
  
  var hasUint8C = (typeof Uint8ClampedArray) !== 'undefined'
  var POOL = global.__TYPEDARRAY_POOL
  
  //Upgrade pool
  if(!POOL.UINT8C) {
    POOL.UINT8C = dup([32, 0])
  }
  if(!POOL.BUFFER) {
    POOL.BUFFER = dup([32, 0])
  }
  
  //New technique: Only allocate from ArrayBufferView and Buffer
  var DATA    = POOL.DATA
    , BUFFER  = POOL.BUFFER
  
  exports.free = function free(array) {
    if(Buffer.isBuffer(array)) {
      BUFFER[bits.log2(array.length)].push(array)
    } else {
      if(Object.prototype.toString.call(array) !== '[object ArrayBuffer]') {
        array = array.buffer
      }
      if(!array) {
        return
      }
      var n = array.length || array.byteLength
      var log_n = bits.log2(n)|0
      DATA[log_n].push(array)
    }
  }
  
  function freeArrayBuffer(buffer) {
    if(!buffer) {
      return
    }
    var n = buffer.length || buffer.byteLength
    var log_n = bits.log2(n)
    DATA[log_n].push(buffer)
  }
  
  function freeTypedArray(array) {
    freeArrayBuffer(array.buffer)
  }
  
  exports.freeUint8 =
  exports.freeUint16 =
  exports.freeUint32 =
  exports.freeInt8 =
  exports.freeInt16 =
  exports.freeInt32 =
  exports.freeFloat32 = 
  exports.freeFloat =
  exports.freeFloat64 = 
  exports.freeDouble = 
  exports.freeUint8Clamped = 
  exports.freeDataView = freeTypedArray
  
  exports.freeArrayBuffer = freeArrayBuffer
  
  exports.freeBuffer = function freeBuffer(array) {
    BUFFER[bits.log2(array.length)].push(array)
  }
  
  exports.malloc = function malloc(n, dtype) {
    if(dtype === undefined || dtype === 'arraybuffer') {
      return mallocArrayBuffer(n)
    } else {
      switch(dtype) {
        case 'uint8':
          return mallocUint8(n)
        case 'uint16':
          return mallocUint16(n)
        case 'uint32':
          return mallocUint32(n)
        case 'int8':
          return mallocInt8(n)
        case 'int16':
          return mallocInt16(n)
        case 'int32':
          return mallocInt32(n)
        case 'float':
        case 'float32':
          return mallocFloat(n)
        case 'double':
        case 'float64':
          return mallocDouble(n)
        case 'uint8_clamped':
          return mallocUint8Clamped(n)
        case 'buffer':
          return mallocBuffer(n)
        case 'data':
        case 'dataview':
          return mallocDataView(n)
  
        default:
          return null
      }
    }
    return null
  }
  
  function mallocArrayBuffer(n) {
    var n = bits.nextPow2(n)
    var log_n = bits.log2(n)
    var d = DATA[log_n]
    if(d.length > 0) {
      return d.pop()
    }
    return new ArrayBuffer(n)
  }
  exports.mallocArrayBuffer = mallocArrayBuffer
  
  function mallocUint8(n) {
    return new Uint8Array(mallocArrayBuffer(n), 0, n)
  }
  exports.mallocUint8 = mallocUint8
  
  function mallocUint16(n) {
    return new Uint16Array(mallocArrayBuffer(2*n), 0, n)
  }
  exports.mallocUint16 = mallocUint16
  
  function mallocUint32(n) {
    return new Uint32Array(mallocArrayBuffer(4*n), 0, n)
  }
  exports.mallocUint32 = mallocUint32
  
  function mallocInt8(n) {
    return new Int8Array(mallocArrayBuffer(n), 0, n)
  }
  exports.mallocInt8 = mallocInt8
  
  function mallocInt16(n) {
    return new Int16Array(mallocArrayBuffer(2*n), 0, n)
  }
  exports.mallocInt16 = mallocInt16
  
  function mallocInt32(n) {
    return new Int32Array(mallocArrayBuffer(4*n), 0, n)
  }
  exports.mallocInt32 = mallocInt32
  
  function mallocFloat(n) {
    return new Float32Array(mallocArrayBuffer(4*n), 0, n)
  }
  exports.mallocFloat32 = exports.mallocFloat = mallocFloat
  
  function mallocDouble(n) {
    return new Float64Array(mallocArrayBuffer(8*n), 0, n)
  }
  exports.mallocFloat64 = exports.mallocDouble = mallocDouble
  
  function mallocUint8Clamped(n) {
    if(hasUint8C) {
      return new Uint8ClampedArray(mallocArrayBuffer(n), 0, n)
    } else {
      return mallocUint8(n)
    }
  }
  exports.mallocUint8Clamped = mallocUint8Clamped
  
  function mallocDataView(n) {
    return new DataView(mallocArrayBuffer(n), 0, n)
  }
  exports.mallocDataView = mallocDataView
  
  function mallocBuffer(n) {
    n = bits.nextPow2(n)
    var log_n = bits.log2(n)
    var cache = BUFFER[log_n]
    if(cache.length > 0) {
      return cache.pop()
    }
    return new Buffer(n)
  }
  exports.mallocBuffer = mallocBuffer
  
  exports.clearCache = function clearCache() {
    for(var i=0; i<32; ++i) {
      POOL.UINT8[i].length = 0
      POOL.UINT16[i].length = 0
      POOL.UINT32[i].length = 0
      POOL.INT8[i].length = 0
      POOL.INT16[i].length = 0
      POOL.INT32[i].length = 0
      POOL.FLOAT[i].length = 0
      POOL.DOUBLE[i].length = 0
      POOL.UINT8C[i].length = 0
      DATA[i].length = 0
      BUFFER[i].length = 0
    }
  }
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
  },{"bit-twiddle":10,"buffer":12,"dup":54}],266:[function(require,module,exports){
  "use strict"
  
  function unique_pred(list, compare) {
    var ptr = 1
      , len = list.length
      , a=list[0], b=list[0]
    for(var i=1; i<len; ++i) {
      b = a
      a = list[i]
      if(compare(a, b)) {
        if(i === ptr) {
          ptr++
          continue
        }
        list[ptr++] = a
      }
    }
    list.length = ptr
    return list
  }
  
  function unique_eq(list) {
    var ptr = 1
      , len = list.length
      , a=list[0], b = list[0]
    for(var i=1; i<len; ++i, b=a) {
      b = a
      a = list[i]
      if(a !== b) {
        if(i === ptr) {
          ptr++
          continue
        }
        list[ptr++] = a
      }
    }
    list.length = ptr
    return list
  }
  
  function unique(list, compare, sorted) {
    if(list.length === 0) {
      return list
    }
    if(compare) {
      if(!sorted) {
        list.sort(compare)
      }
      return unique_pred(list, compare)
    }
    if(!sorted) {
      list.sort()
    }
    return unique_eq(list)
  }
  
  module.exports = unique
  
  },{}],267:[function(require,module,exports){
  module.exports = urlSetQuery
  function urlSetQuery (url, query) {
    if (query) {
      // remove optional leading symbols
      query = query.trim().replace(/^(\?|#|&)/, '')
  
      // don't append empty query
      query = query ? ('?' + query) : query
  
      var parts = url.split(/[\?\#]/)
      var start = parts[0]
      if (query && /\:\/\/[^\/]*$/.test(start)) {
        // e.g. http://foo.com -> http://foo.com/
        start = start + '/'
      }
      var match = url.match(/(\#.*)$/)
      url = start + query
      if (match) { // add hash back in
        url = url + match[0]
      }
    }
    return url
  }
  
  },{}],268:[function(require,module,exports){
  module.exports = function isBuffer(arg) {
    return arg && typeof arg === 'object'
      && typeof arg.copy === 'function'
      && typeof arg.fill === 'function'
      && typeof arg.readUInt8 === 'function';
  }
  },{}],269:[function(require,module,exports){
  (function (process,global){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  var formatRegExp = /%[sdj%]/g;
  exports.format = function(f) {
    if (!isString(f)) {
      var objects = [];
      for (var i = 0; i < arguments.length; i++) {
        objects.push(inspect(arguments[i]));
      }
      return objects.join(' ');
    }
  
    var i = 1;
    var args = arguments;
    var len = args.length;
    var str = String(f).replace(formatRegExp, function(x) {
      if (x === '%%') return '%';
      if (i >= len) return x;
      switch (x) {
        case '%s': return String(args[i++]);
        case '%d': return Number(args[i++]);
        case '%j':
          try {
            return JSON.stringify(args[i++]);
          } catch (_) {
            return '[Circular]';
          }
        default:
          return x;
      }
    });
    for (var x = args[i]; i < len; x = args[++i]) {
      if (isNull(x) || !isObject(x)) {
        str += ' ' + x;
      } else {
        str += ' ' + inspect(x);
      }
    }
    return str;
  };
  
  
  // Mark that a method should not be used.
  // Returns a modified function which warns once by default.
  // If --no-deprecation is set, then it is a no-op.
  exports.deprecate = function(fn, msg) {
    // Allow for deprecating things in the process of starting up.
    if (isUndefined(global.process)) {
      return function() {
        return exports.deprecate(fn, msg).apply(this, arguments);
      };
    }
  
    if (process.noDeprecation === true) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (process.throwDeprecation) {
          throw new Error(msg);
        } else if (process.traceDeprecation) {
          console.trace(msg);
        } else {
          console.error(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  };
  
  
  var debugs = {};
  var debugEnviron;
  exports.debuglog = function(set) {
    if (isUndefined(debugEnviron))
      debugEnviron = process.env.NODE_DEBUG || '';
    set = set.toUpperCase();
    if (!debugs[set]) {
      if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
        var pid = process.pid;
        debugs[set] = function() {
          var msg = exports.format.apply(exports, arguments);
          console.error('%s %d: %s', set, pid, msg);
        };
      } else {
        debugs[set] = function() {};
      }
    }
    return debugs[set];
  };
  
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Object} opts Optional options object that alters the output.
   */
  /* legacy: obj, showHidden, depth, colors*/
  function inspect(obj, opts) {
    // default options
    var ctx = {
      seen: [],
      stylize: stylizeNoColor
    };
    // legacy...
    if (arguments.length >= 3) ctx.depth = arguments[2];
    if (arguments.length >= 4) ctx.colors = arguments[3];
    if (isBoolean(opts)) {
      // legacy...
      ctx.showHidden = opts;
    } else if (opts) {
      // got an "options" object
      exports._extend(ctx, opts);
    }
    // set default options
    if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
    if (isUndefined(ctx.depth)) ctx.depth = 2;
    if (isUndefined(ctx.colors)) ctx.colors = false;
    if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
    if (ctx.colors) ctx.stylize = stylizeWithColor;
    return formatValue(ctx, obj, ctx.depth);
  }
  exports.inspect = inspect;
  
  
  // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  inspect.colors = {
    'bold' : [1, 22],
    'italic' : [3, 23],
    'underline' : [4, 24],
    'inverse' : [7, 27],
    'white' : [37, 39],
    'grey' : [90, 39],
    'black' : [30, 39],
    'blue' : [34, 39],
    'cyan' : [36, 39],
    'green' : [32, 39],
    'magenta' : [35, 39],
    'red' : [31, 39],
    'yellow' : [33, 39]
  };
  
  // Don't use 'blue' not visible on cmd.exe
  inspect.styles = {
    'special': 'cyan',
    'number': 'yellow',
    'boolean': 'yellow',
    'undefined': 'grey',
    'null': 'bold',
    'string': 'green',
    'date': 'magenta',
    // "name": intentionally not styling
    'regexp': 'red'
  };
  
  
  function stylizeWithColor(str, styleType) {
    var style = inspect.styles[styleType];
  
    if (style) {
      return '\u001b[' + inspect.colors[style][0] + 'm' + str +
             '\u001b[' + inspect.colors[style][1] + 'm';
    } else {
      return str;
    }
  }
  
  
  function stylizeNoColor(str, styleType) {
    return str;
  }
  
  
  function arrayToHash(array) {
    var hash = {};
  
    array.forEach(function(val, idx) {
      hash[val] = true;
    });
  
    return hash;
  }
  
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (ctx.customInspect &&
        value &&
        isFunction(value.inspect) &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes, ctx);
      if (!isString(ret)) {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // Look up the keys of the object.
    var keys = Object.keys(value);
    var visibleKeys = arrayToHash(keys);
  
    if (ctx.showHidden) {
      keys = Object.getOwnPropertyNames(value);
    }
  
    // IE doesn't make error fields non-enumerable
    // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
    if (isError(value)
        && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
      return formatError(value);
    }
  
    // Some type of object without properties can be shortcutted.
    if (keys.length === 0) {
      if (isFunction(value)) {
        var name = value.name ? ': ' + value.name : '';
        return ctx.stylize('[Function' + name + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (isFunction(value)) {
      var n = value.name ? ': ' + value.name : '';
      base = ' [Function' + n + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      base = ' ' + formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    if (isUndefined(value))
      return ctx.stylize('undefined', 'undefined');
    if (isString(value)) {
      var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                               .replace(/'/g, "\\'")
                                               .replace(/\\"/g, '"') + '\'';
      return ctx.stylize(simple, 'string');
    }
    if (isNumber(value))
      return ctx.stylize('' + value, 'number');
    if (isBoolean(value))
      return ctx.stylize('' + value, 'boolean');
    // For some reason typeof null is "object", so special case here.
    if (isNull(value))
      return ctx.stylize('null', 'null');
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (hasOwnProperty(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str, desc;
    desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
    if (desc.get) {
      if (desc.set) {
        str = ctx.stylize('[Getter/Setter]', 'special');
      } else {
        str = ctx.stylize('[Getter]', 'special');
      }
    } else {
      if (desc.set) {
        str = ctx.stylize('[Setter]', 'special');
      }
    }
    if (!hasOwnProperty(visibleKeys, key)) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(desc.value) < 0) {
        if (isNull(recurseTimes)) {
          str = formatValue(ctx, desc.value, null);
        } else {
          str = formatValue(ctx, desc.value, recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (isUndefined(name)) {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  function isArray(ar) {
    return Array.isArray(ar);
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = require('./support/isBuffer');
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  
  function pad(n) {
    return n < 10 ? '0' + n.toString(10) : n.toString(10);
  }
  
  
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'];
  
  // 26 Feb 16:19:34
  function timestamp() {
    var d = new Date();
    var time = [pad(d.getHours()),
                pad(d.getMinutes()),
                pad(d.getSeconds())].join(':');
    return [d.getDate(), months[d.getMonth()], time].join(' ');
  }
  
  
  // log is just a thin wrapper to console.log that prepends a timestamp
  exports.log = function() {
    console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
  };
  
  
  /**
   * Inherit the prototype methods from one constructor into another.
   *
   * The Function.prototype.inherits from lang.js rewritten as a standalone
   * function (not on Function.prototype). NOTE: If this file is to be loaded
   * during bootstrapping this function needs to be rewritten using some native
   * functions as prototype setup using normal JavaScript does not work as
   * expected during bootstrapping (see mirror.js in r114903).
   *
   * @param {function} ctor Constructor function which needs to inherit the
   *     prototype.
   * @param {function} superCtor Constructor function to inherit prototype from.
   */
  exports.inherits = require('inherits');
  
  exports._extend = function(origin, add) {
    // Don't do anything if add isn't an object
    if (!add || !isObject(add)) return origin;
  
    var keys = Object.keys(add);
    var i = keys.length;
    while (i--) {
      origin[keys[i]] = add[keys[i]];
    }
    return origin;
  };
  
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./support/isBuffer":268,"_process":11,"inherits":194}],270:[function(require,module,exports){
  var ua = typeof window !== 'undefined' ? window.navigator.userAgent : ''
    , isOSX = /OS X/.test(ua)
    , isOpera = /Opera/.test(ua)
    , maybeFirefox = !/like Gecko/.test(ua) && !isOpera
  
  var i, output = module.exports = {
    0:  isOSX ? '<menu>' : '<UNK>'
  , 1:  '<mouse 1>'
  , 2:  '<mouse 2>'
  , 3:  '<break>'
  , 4:  '<mouse 3>'
  , 5:  '<mouse 4>'
  , 6:  '<mouse 5>'
  , 8:  '<backspace>'
  , 9:  '<tab>'
  , 12: '<clear>'
  , 13: '<enter>'
  , 16: '<shift>'
  , 17: '<control>'
  , 18: '<alt>'
  , 19: '<pause>'
  , 20: '<caps-lock>'
  , 21: '<ime-hangul>'
  , 23: '<ime-junja>'
  , 24: '<ime-final>'
  , 25: '<ime-kanji>'
  , 27: '<escape>'
  , 28: '<ime-convert>'
  , 29: '<ime-nonconvert>'
  , 30: '<ime-accept>'
  , 31: '<ime-mode-change>'
  , 27: '<escape>'
  , 32: '<space>'
  , 33: '<page-up>'
  , 34: '<page-down>'
  , 35: '<end>'
  , 36: '<home>'
  , 37: '<left>'
  , 38: '<up>'
  , 39: '<right>'
  , 40: '<down>'
  , 41: '<select>'
  , 42: '<print>'
  , 43: '<execute>'
  , 44: '<snapshot>'
  , 45: '<insert>'
  , 46: '<delete>'
  , 47: '<help>'
  , 91: '<meta>'  // meta-left -- no one handles left and right properly, so we coerce into one.
  , 92: '<meta>'  // meta-right
  , 93: isOSX ? '<meta>' : '<menu>'      // chrome,opera,safari all report this for meta-right (osx mbp).
  , 95: '<sleep>'
  , 106: '<num-*>'
  , 107: '<num-+>'
  , 108: '<num-enter>'
  , 109: '<num-->'
  , 110: '<num-.>'
  , 111: '<num-/>'
  , 144: '<num-lock>'
  , 145: '<scroll-lock>'
  , 160: '<shift-left>'
  , 161: '<shift-right>'
  , 162: '<control-left>'
  , 163: '<control-right>'
  , 164: '<alt-left>'
  , 165: '<alt-right>'
  , 166: '<browser-back>'
  , 167: '<browser-forward>'
  , 168: '<browser-refresh>'
  , 169: '<browser-stop>'
  , 170: '<browser-search>'
  , 171: '<browser-favorites>'
  , 172: '<browser-home>'
  
    // ff/osx reports '<volume-mute>' for '-'
  , 173: isOSX && maybeFirefox ? '-' : '<volume-mute>'
  , 174: '<volume-down>'
  , 175: '<volume-up>'
  , 176: '<next-track>'
  , 177: '<prev-track>'
  , 178: '<stop>'
  , 179: '<play-pause>'
  , 180: '<launch-mail>'
  , 181: '<launch-media-select>'
  , 182: '<launch-app 1>'
  , 183: '<launch-app 2>'
  , 186: ';'
  , 187: '='
  , 188: ','
  , 189: '-'
  , 190: '.'
  , 191: '/'
  , 192: '`'
  , 219: '['
  , 220: '\\'
  , 221: ']'
  , 222: "'"
  , 223: '<meta>'
  , 224: '<meta>'       // firefox reports meta here.
  , 226: '<alt-gr>'
  , 229: '<ime-process>'
  , 231: isOpera ? '`' : '<unicode>'
  , 246: '<attention>'
  , 247: '<crsel>'
  , 248: '<exsel>'
  , 249: '<erase-eof>'
  , 250: '<play>'
  , 251: '<zoom>'
  , 252: '<no-name>'
  , 253: '<pa-1>'
  , 254: '<clear>'
  }
  
  for(i = 58; i < 65; ++i) {
    output[i] = String.fromCharCode(i)
  }
  
  // 0-9
  for(i = 48; i < 58; ++i) {
    output[i] = (i - 48)+''
  }
  
  // A-Z
  for(i = 65; i < 91; ++i) {
    output[i] = String.fromCharCode(i)
  }
  
  // num0-9
  for(i = 96; i < 106; ++i) {
    output[i] = '<num-'+(i - 96)+'>'
  }
  
  // F1-F24
  for(i = 112; i < 136; ++i) {
    output[i] = 'F'+(i-111)
  }
  
  },{}],271:[function(require,module,exports){
  var hiddenStore = require('./hidden-store.js');
  
  module.exports = createStore;
  
  function createStore() {
      var key = {};
  
      return function (obj) {
          if ((typeof obj !== 'object' || obj === null) &&
              typeof obj !== 'function'
          ) {
              throw new Error('Weakmap-shim: Key must be object')
          }
  
          var store = obj.valueOf(key);
          return store && store.identity === key ?
              store : hiddenStore(obj, key);
      };
  }
  
  },{"./hidden-store.js":272}],272:[function(require,module,exports){
  module.exports = hiddenStore;
  
  function hiddenStore(obj, key) {
      var store = { identity: key };
      var valueOf = obj.valueOf;
  
      Object.defineProperty(obj, "valueOf", {
          value: function (value) {
              return value !== key ?
                  valueOf.apply(this, arguments) : store;
          },
          writable: true
      });
  
      return store;
  }
  
  },{}],273:[function(require,module,exports){
  // Original - @Gozola. 
  // https://gist.github.com/Gozala/1269991
  // This is a reimplemented version (with a few bug fixes).
  
  var createStore = require('./create-store.js');
  
  module.exports = weakMap;
  
  function weakMap() {
      var privates = createStore();
  
      return {
          'get': function (key, fallback) {
              var store = privates(key)
              return store.hasOwnProperty('value') ?
                  store.value : fallback
          },
          'set': function (key, value) {
              privates(key).value = value;
          },
          'has': function(key) {
              return 'value' in privates(key);
          },
          'delete': function (key) {
              return delete privates(key).value;
          }
      }
  }
  
  },{"./create-store.js":271}],274:[function(require,module,exports){
  var queryString = require('query-string')
  var setQuery = require('url-set-query')
  var assign = require('object-assign')
  var ensureHeader = require('./lib/ensure-header.js')
  
  // this is replaced in the browser
  var request = require('./lib/request.js')
  
  var mimeTypeJson = 'application/json'
  var noop = function () {}
  
  module.exports = xhrRequest
  function xhrRequest (url, opt, cb) {
    if (!url || typeof url !== 'string') {
      throw new TypeError('must specify a URL')
    }
    if (typeof opt === 'function') {
      cb = opt
      opt = {}
    }
    if (cb && typeof cb !== 'function') {
      throw new TypeError('expected cb to be undefined or a function')
    }
  
    cb = cb || noop
    opt = opt || {}
  
    var defaultResponse = opt.json ? 'json' : 'text'
    opt = assign({ responseType: defaultResponse }, opt)
  
    var headers = opt.headers || {}
    var method = (opt.method || 'GET').toUpperCase()
    var query = opt.query
    if (query) {
      if (typeof query !== 'string') {
        query = queryString.stringify(query)
      }
      url = setQuery(url, query)
    }
  
    // allow json response
    if (opt.responseType === 'json') {
      ensureHeader(headers, 'Accept', mimeTypeJson)
    }
  
    // if body content is json
    if (opt.json && method !== 'GET' && method !== 'HEAD') {
      ensureHeader(headers, 'Content-Type', mimeTypeJson)
      opt.body = JSON.stringify(opt.body)
    }
  
    opt.method = method
    opt.url = url
    opt.headers = headers
    delete opt.query
    delete opt.json
  
    return request(opt, cb)
  }
  
  },{"./lib/ensure-header.js":275,"./lib/request.js":277,"object-assign":207,"query-string":242,"url-set-query":267}],275:[function(require,module,exports){
  module.exports = ensureHeader
  function ensureHeader (headers, key, value) {
    var lower = key.toLowerCase()
    if (!headers[key] && !headers[lower]) {
      headers[key] = value
    }
  }
  
  },{}],276:[function(require,module,exports){
  module.exports = getResponse
  function getResponse (opt, resp) {
    if (!resp) return null
    return {
      statusCode: resp.statusCode,
      headers: resp.headers,
      method: opt.method,
      url: opt.url,
      // the XHR object in browser, http response in Node
      rawRequest: resp.rawRequest ? resp.rawRequest : resp
    }
  }
  
  },{}],277:[function(require,module,exports){
  var xhr = require('xhr')
  var normalize = require('./normalize-response')
  
  module.exports = xhrRequest
  function xhrRequest (opt, cb) {
    delete opt.uri
  
    // for better JSON.parse error handling than xhr module
    var useJson = false
    if (opt.responseType === 'json') {
      opt.responseType = 'text'
      useJson = true
    }
  
    return xhr(opt, function xhrRequestResult (err, resp, body) {
      if (useJson && !err) {
        try {
          var text = resp.rawRequest.responseText
          body = JSON.parse(text)
        } catch (e) {
          err = e
        }
      }
  
      resp = normalize(opt, resp)
      if (err) cb(err, null, resp)
      else cb(err, body, resp)
    })
  }
  
  },{"./normalize-response":276,"xhr":278}],278:[function(require,module,exports){
  "use strict";
  var window = require("global/window")
  var once = require("once")
  var isFunction = require("is-function")
  var parseHeaders = require("parse-headers")
  var xtend = require("xtend")
  
  module.exports = createXHR
  createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
  createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest
  
  forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
      createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
          options = initParams(uri, options, callback)
          options.method = method.toUpperCase()
          return _createXHR(options)
      }
  })
  
  function forEachArray(array, iterator) {
      for (var i = 0; i < array.length; i++) {
          iterator(array[i])
      }
  }
  
  function isEmpty(obj){
      for(var i in obj){
          if(obj.hasOwnProperty(i)) return false
      }
      return true
  }
  
  function initParams(uri, options, callback) {
      var params = uri
  
      if (isFunction(options)) {
          callback = options
          if (typeof uri === "string") {
              params = {uri:uri}
          }
      } else {
          params = xtend(options, {uri: uri})
      }
  
      params.callback = callback
      return params
  }
  
  function createXHR(uri, options, callback) {
      options = initParams(uri, options, callback)
      return _createXHR(options)
  }
  
  function _createXHR(options) {
      var callback = options.callback
      if(typeof callback === "undefined"){
          throw new Error("callback argument missing")
      }
      callback = once(callback)
  
      function readystatechange() {
          if (xhr.readyState === 4) {
              loadFunc()
          }
      }
  
      function getBody() {
          // Chrome with requestType=blob throws errors arround when even testing access to responseText
          var body = undefined
  
          if (xhr.response) {
              body = xhr.response
          } else if (xhr.responseType === "text" || !xhr.responseType) {
              body = xhr.responseText || xhr.responseXML
          }
  
          if (isJson) {
              try {
                  body = JSON.parse(body)
              } catch (e) {}
          }
  
          return body
      }
  
      var failureResponse = {
                  body: undefined,
                  headers: {},
                  statusCode: 0,
                  method: method,
                  url: uri,
                  rawRequest: xhr
              }
  
      function errorFunc(evt) {
          clearTimeout(timeoutTimer)
          if(!(evt instanceof Error)){
              evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
          }
          evt.statusCode = 0
          callback(evt, failureResponse)
      }
  
      // will load the data & process the response in a special response object
      function loadFunc() {
          if (aborted) return
          var status
          clearTimeout(timeoutTimer)
          if(options.useXDR && xhr.status===undefined) {
              //IE8 CORS GET successful response doesn't have a status field, but body is fine
              status = 200
          } else {
              status = (xhr.status === 1223 ? 204 : xhr.status)
          }
          var response = failureResponse
          var err = null
  
          if (status !== 0){
              response = {
                  body: getBody(),
                  statusCode: status,
                  method: method,
                  headers: {},
                  url: uri,
                  rawRequest: xhr
              }
              if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
                  response.headers = parseHeaders(xhr.getAllResponseHeaders())
              }
          } else {
              err = new Error("Internal XMLHttpRequest Error")
          }
          callback(err, response, response.body)
  
      }
  
      var xhr = options.xhr || null
  
      if (!xhr) {
          if (options.cors || options.useXDR) {
              xhr = new createXHR.XDomainRequest()
          }else{
              xhr = new createXHR.XMLHttpRequest()
          }
      }
  
      var key
      var aborted
      var uri = xhr.url = options.uri || options.url
      var method = xhr.method = options.method || "GET"
      var body = options.body || options.data || null
      var headers = xhr.headers = options.headers || {}
      var sync = !!options.sync
      var isJson = false
      var timeoutTimer
  
      if ("json" in options) {
          isJson = true
          headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
          if (method !== "GET" && method !== "HEAD") {
              headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
              body = JSON.stringify(options.json)
          }
      }
  
      xhr.onreadystatechange = readystatechange
      xhr.onload = loadFunc
      xhr.onerror = errorFunc
      // IE9 must have onprogress be set to a unique function.
      xhr.onprogress = function () {
          // IE must die
      }
      xhr.ontimeout = errorFunc
      xhr.open(method, uri, !sync, options.username, options.password)
      //has to be after open
      if(!sync) {
          xhr.withCredentials = !!options.withCredentials
      }
      // Cannot set timeout with sync request
      // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
      // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
      if (!sync && options.timeout > 0 ) {
          timeoutTimer = setTimeout(function(){
              aborted=true//IE9 may still call readystatechange
              xhr.abort("timeout")
              var e = new Error("XMLHttpRequest timeout")
              e.code = "ETIMEDOUT"
              errorFunc(e)
          }, options.timeout )
      }
  
      if (xhr.setRequestHeader) {
          for(key in headers){
              if(headers.hasOwnProperty(key)){
                  xhr.setRequestHeader(key, headers[key])
              }
          }
      } else if (options.headers && !isEmpty(options.headers)) {
          throw new Error("Headers cannot be set on an XDomainRequest object")
      }
  
      if ("responseType" in options) {
          xhr.responseType = options.responseType
      }
  
      if ("beforeSend" in options &&
          typeof options.beforeSend === "function"
      ) {
          options.beforeSend(xhr)
      }
  
      xhr.send(body)
  
      return xhr
  
  
  }
  
  function noop() {}
  
  },{"global/window":185,"is-function":198,"once":208,"parse-headers":211,"xtend":279}],279:[function(require,module,exports){
  module.exports = extend
  
  var hasOwnProperty = Object.prototype.hasOwnProperty;
  
  function extend() {
      var target = {}
  
      for (var i = 0; i < arguments.length; i++) {
          var source = arguments[i]
  
          for (var key in source) {
              if (hasOwnProperty.call(source, key)) {
                  target[key] = source[key]
              }
          }
      }
  
      return target
  }
  
  },{}]},{},[1]);
  