text: (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.TF = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  var sprintf = require('sprintf');
  module.exports = format;
  
  function format (x, bytes) {
      if (bytes === undefined) bytes = 8;
      var rfmt = '%' + bytes + '.' + bytes + 's';
      
      if (bytes <= 0) return undefined;
      if (isNaN(x)) return sprintf(rfmt, 'NaN');
      if (x === Infinity) {
          if (bytes === 1) return undefined;
          return sprintf(rfmt, bytes >= 9 ? 'Infinity' : ' Inf').slice(0, bytes);
      }
      if (x === -Infinity) {
          if (bytes === 1) return undefined;
          return sprintf(rfmt, bytes >= 9 ? '-Infinity' : '-Inf').slice(0, bytes);
      }
      return packf(x, bytes);
  };
  
  function sci (x, bytes) {
      var n = Math.max(1, log10f(Math.abs(x)));
      var sz = log10f(Math.abs(n));
      
      var b = Math.pow(10,bytes+1);
      if (Math.abs(x) < 1) {
          x = Math.round(x * b) / b;
      }
      else {
          var tn = Math.pow(10, n + 1);
          x = Math.round(x / tn * b) / b * tn;
      }
      
      var s;
      if (bytes - sz - 6 === -1) {
          x = Math.round(x / Math.pow(10, n));
          x = x * Math.pow(10, n);
          s = sprintf('%1e', x).replace(/\.[^e]+/, '');
      }
      else if (bytes - sz - 6 < 0) return undefined;
      else {
          s = sprintf('%.' + (bytes - sz - 6) + 'e', x);
      }
      if (x > 0) s = ' ' + s;
      return pad(s, bytes);
  }
  
  function pad (s, bytes) {
      return Array(Math.max(0, bytes - s.length + 1)).join(' ') + s;
  }
  
  function log10f (n) {
      return Math.floor(Math.log(n) / Math.log(10));
  }
  
  function packf (x, bytes) {
      var lbytes = Math.max(1, Math.floor((bytes - 2) / 2));
      var rbytes = bytes - lbytes - 2;
      
      if (x === 0 && bytes < 4) {
          return pad('0', bytes);
      }
      else if (x === 0) {
          return pad('0.' + Array(rbytes+1).join('0'), bytes);
      }
      
      if (rbytes <= 0) {
          var s = sprintf('%' + lbytes + 'f', x);
          if (x >= 0) s = ' ' + s;
          if (s.length > bytes) return undefined;
          return pad(s, bytes);
      }
      if (Math.abs(x) < Math.pow(10,1-rbytes)) return sci(x, bytes);
      
      var b = Math.pow(10,bytes-3);
      var tn = Math.pow(10, log10f(Math.abs(x)));
      var xr = Math.round(x / tn * b) / b * tn;
      
      var s = sprintf('%' + lbytes + '.' + rbytes + 'f', xr);
      if (xr > 0) s = ' ' + s;
      s = s.slice(0, bytes);
      var r = s.split('.')[1];
      if (!r || r.length < 1) return sci(xr, bytes);
      return pad(s, bytes).slice(0, bytes);
  }
  
  },{"sprintf":6}],2:[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
  },{}],3:[function(require,module,exports){
  /*!
   * Determine if an object is a Buffer
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  
  // The _isBuffer check is for Safari 5-7 support, because it's missing
  // Object.prototype.constructor. Remove this eventually
  module.exports = function (obj) {
    return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
  }
  
  function isBuffer (obj) {
    return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
  }
  
  // For Node v0.10 support. Remove this eventually.
  function isSlowBuffer (obj) {
    return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
  }
  
  },{}],4:[function(require,module,exports){
  var showf = require('fixed-width-float');
  var ndarray = require('ndarray');
  
  module.exports = function (m, opts) {
      if (!opts) opts = {};
      if (typeof opts === 'number') opts = { width: opts };
      if (!opts.width) opts.width = 8;
  
      if (m.dimension === undefined) {
          m = ndarray(m);
      }
  
      if (m.dimension === 1) return d1(m, opts);
      if (m.dimension === 2) return d2(m, opts);
      if (m.dimension === 3) return d3(m, opts);
      if (m.dimension === 4) return d4(m, opts);
  };
  
  function d1 (m, opts) {
      var terms = [];
      for (var i = 0; i < m.shape[0]; i++) {
          terms.push(showf(m.get(i), opts.width));
      }
      return terms.join(' ');
  }
  
  function d2 (m, opts) {
      var rows = [];
      for (var y = 0; y < m.shape[0]; y++) {
          rows.push(d1(m.pick(y, null), opts));
      }
      return rows.join('\n');
  }
  
  function d3 (m, opts) {
      var rows = [];
      for (var z = 0; z < m.shape[0]; z++) {
          rows.push(d2(m.pick(z, null, null), opts), '');
      }
      return rows.join('\n');
  }
  
  function d4 (m, opts) {
      var rows = [], len = 3
      for (var w = 0; w < m.shape[0]; w++) {
          var r = d3(m.pick(w, null, null, null), opts)
          rows.push(r);
          var lines = r.split('\n');
          for (var i = 0; i < lines.length; i++) {
              len = Math.max(len, lines[i].length);
          }
      }
      return rows.join('\n' + Array(len+1).join('-') + '\n\n');
  }
  
  },{"fixed-width-float":1,"ndarray":5}],5:[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":2,"is-buffer":3}],6:[function(require,module,exports){
  /**
  sprintf() for JavaScript 0.7-beta1
  http://www.diveintojavascript.com/projects/javascript-sprintf
  
  Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
  All rights reserved.
  
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
      * Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
      * Neither the name of sprintf() for JavaScript nor the
        names of its contributors may be used to endorse or promote products
        derived from this software without specific prior written permission.
  
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  
  Changelog:
  2010.11.07 - 0.7-beta1-node
    - converted it to a node.js compatible module
  
  2010.09.06 - 0.7-beta1
    - features: vsprintf, support for named placeholders
    - enhancements: format cache, reduced global namespace pollution
  
  2010.05.22 - 0.6:
   - reverted to 0.4 and fixed the bug regarding the sign of the number 0
   Note:
   Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/)
   who warned me about a bug in 0.5, I discovered that the last update was
   a regress. I appologize for that.
  
  2010.05.09 - 0.5:
   - bug fix: 0 is now preceeded with a + sign
   - bug fix: the sign was not at the right position on padded results (Kamal Abdali)
   - switched from GPL to BSD license
  
  2007.10.21 - 0.4:
   - unit test and patch (David Baird)
  
  2007.09.17 - 0.3:
   - bug fix: no longer throws exception on empty paramenters (Hans Pufal)
  
  2007.09.11 - 0.2:
   - feature: added argument swapping
  
  2007.04.03 - 0.1:
   - initial release
  **/
  
  var sprintf = (function() {
    function get_type(variable) {
      return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
    }
    function str_repeat(input, multiplier) {
      for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
      return output.join('');
    }
  
    var str_format = function() {
      if (!str_format.cache.hasOwnProperty(arguments[0])) {
        str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
      }
      return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
    };
  
    // convert object to simple one line string without indentation or
    // newlines. Note that this implementation does not print array
    // values to their actual place for sparse arrays. 
    //
    // For example sparse array like this
    //    l = []
    //    l[4] = 1
    // Would be printed as "[1]" instead of "[, , , , 1]"
    // 
    // If argument 'seen' is not null and array the function will check for 
    // circular object references from argument.
    str_format.object_stringify = function(obj, depth, maxdepth, seen) {
      var str = '';
      if (obj != null) {
        switch( typeof(obj) ) {
        case 'function': 
          return '[Function' + (obj.name ? ': '+obj.name : '') + ']';
            break;
        case 'object':
          if ( obj instanceof Error) { return '[' + obj.toString() + ']' };
          if (depth >= maxdepth) return '[Object]'
          if (seen) {
            // add object to seen list
            seen = seen.slice(0)
            seen.push(obj);
          }
          if (obj.length != null) { //array
            str += '[';
            var arr = []
            for (var i in obj) {
              if (seen && seen.indexOf(obj[i]) >= 0) arr.push('[Circular]');
              else arr.push(str_format.object_stringify(obj[i], depth+1, maxdepth, seen));
            }
            str += arr.join(', ') + ']';
          } else if ('getMonth' in obj) { // date
            return 'Date(' + obj + ')';
          } else { // object
            str += '{';
            var arr = []
            for (var k in obj) { 
              if(obj.hasOwnProperty(k)) {
                if (seen && seen.indexOf(obj[k]) >= 0) arr.push(k + ': [Circular]');
                else arr.push(k +': ' +str_format.object_stringify(obj[k], depth+1, maxdepth, seen)); 
              }
            }
            str += arr.join(', ') + '}';
          }
          return str;
          break;
        case 'string':        
          return '"' + obj + '"';
          break
        }
      }
      return '' + obj;
    }
  
    str_format.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;
      for (i = 0; i < tree_length; i++) {
        node_type = get_type(parse_tree[i]);
        if (node_type === 'string') {
          output.push(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 (/[^sO]/.test(match[8]) && (get_type(arg) != 'number')) {
            throw new Error(sprintf('[sprintf] expecting number but found %s "' + arg + '"', get_type(arg)));
          }
          switch (match[8]) {
            case 'b': arg = arg.toString(2); break;
            case 'c': arg = String.fromCharCode(arg); break;
            case 'd': arg = parseInt(arg, 10); 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 'O': arg = str_format.object_stringify(arg, 0, parseInt(match[7]) || 5); 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 = Math.abs(arg); break;
            case 'x': arg = arg.toString(16); break;
            case 'X': arg = arg.toString(16).toUpperCase(); break;
          }
          arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
          pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
          pad_length = match[6] - String(arg).length;
          pad = match[6] ? str_repeat(pad_character, pad_length) : '';
          output.push(match[5] ? arg + pad : pad + arg);
        }
      }
      return output.join('');
    };
  
    str_format.cache = {};
  
    str_format.parse = function(fmt) {
      var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
      while (_fmt) {
        if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
          parse_tree.push(match[0]);
        }
        else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
          parse_tree.push('%');
        }
        else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosOuxX])/.exec(_fmt)) !== null) {
          if (match[2]) {
            arg_names |= 1;
            var field_list = [], replacement_field = match[2], field_match = [];
            if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
              field_list.push(field_match[1]);
              while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
                if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
                  field_list.push(field_match[1]);
                }
                else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
                  field_list.push(field_match[1]);
                }
                else {
                  throw new Error('[sprintf] ' + replacement_field);
                }
              }
            }
            else {
                          throw new Error('[sprintf] ' + replacement_field);
            }
            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.push(match);
        }
        else {
          throw new Error('[sprintf] ' + _fmt);
        }
        _fmt = _fmt.substring(match[0].length);
      }
      return parse_tree;
    };
  
    return str_format;
  })();
  
  var vsprintf = function(fmt, argv) {
    var argvClone = argv.slice();
    argvClone.unshift(fmt);
    return sprintf.apply(null, argvClone);
  };
  
  module.exports = sprintf;
  sprintf.sprintf = sprintf;
  sprintf.vsprintf = vsprintf;
  
  },{}],7:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.default = {
    hard_sigmoid: 'float @activation1(float data){\n    return clamp(data * 0.2 + 0.5, 0.0, 1.0);\n}',
    linear: '#define @activation1 \n',
    relu: 'float @activation1(float data){\n    return max(data, 0.0);\n}\n',
    rgb: 'float @activation1(float data){\n    return data / 255.0; \n}',
    sigmoid: 'float @activation1(float data){\n    return (1.0/(1.0 + exp(-2.0 * \n        clamp(data,-20.0, 20.0) )));\n}\n',
    tanh: 'float @activation1(float data){\n    float e = exp(2.0 * clamp(data, -20.0, 20.0) );\n    return (e-1.0)/(e+1.0);\n}'
  };
  
  },{}],8:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.init = init;
  exports.encode = encode;
  exports.decode = decode;
  var encodeShader = exports.encodeShader = 'uniform float @range;\n\nvec4 @encode1(float v) {\n\tfloat z = clamp(v / @range + 0.5, 0.0, 1.0);\n\n\treturn mod(z * vec4(\n\t\t256.0 * 256.0 * 256.0 * 256.0,\n\t\t256.0 * 256.0 * 256.0,\n\t\t256.0 * 256.0,\n\t\t256.0\n\t), vec4(256.0)) / 255.0;\n}';
  var decodeShader = exports.decodeShader = 'uniform float @range;\n\nfloat @decode1(vec4 rgba) {\n\tfloat f = dot(rgba, vec4(\n\t\t255.0 / 256.0 / 256.0 / 256.0 / 256.0,\n\t\t255.0 / 256.0 / 256.0 / 256.0,\n\t\t255.0 / 256.0 / 256.0,\n\t\t255.0 / 256.0\n\t));\n\treturn (f - 0.5) * @range;\n}';
  
  function init(shape, format) {
    return {
      range: format.range || 4096
    };
  }
  
  function encode(buf, value, info) {
    var z = Math.min(1, Math.max(0, value / info.range + 0.5));
    buf[0] = z * 256 * 256 * 256 * 256 % 256;
    buf[1] = z * 256 * 256 * 256 % 256;
    buf[2] = z * 256 * 256 % 256;
    buf[3] = z * 256 % 256;
  }
  
  function decode(buf) {
    return buf[0] / 256.0 / 256.0 / 256.0 / 256.0 + buf[1] / 256.0 / 256.0 / 256.0 + buf[2] / 256.0 / 256.0 + buf[3] / 256.0;
  }
  
  },{}],9:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.init = init;
  exports.encode = encode;
  exports.decode = decode;
  var encodeShader = exports.encodeShader = '// https://github.com/mikolalysenko/glsl-read-float/blob/master/index.glsl\n\n#define FLOAT_MAX  1.70141184e38\n#define FLOAT_MIN  1.17549435e-38\n\nvec4 @encode1(float v) {\n    highp float av = abs(v);\n\n    //Handle special cases\n    if(av < FLOAT_MIN) {\n        return vec4(0.0, 0.0, 0.0, 0.0);\n    } else if(v > FLOAT_MAX) {\n        return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;\n    } else if(v < -FLOAT_MAX) {\n        return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;\n    }\n\n    highp vec4 c = vec4(0,0,0,0);\n\n    //Compute exponent and mantissa\n    highp float e = floor(log2(av));\n    highp float m = av * pow(2.0, -e) - 1.0;\n    \n    //Unpack mantissa\n    c[1] = floor(128.0 * m);\n    m -= c[1] / 128.0;\n    c[2] = floor(32768.0 * m);\n    m -= c[2] / 32768.0;\n    c[3] = floor(8388608.0 * m);\n    \n    //Unpack exponent\n    highp float ebias = e + 127.0;\n    c[0] = floor(ebias / 2.0);\n    ebias -= c[0] * 2.0;\n    c[1] += floor(ebias) * 128.0; \n\n    //Unpack sign bit\n    c[0] += 128.0 * step(0.0, -v);\n\n    //Scale back to range\n    return c.abgr / 255.0;\n}\n\n// TODO: compare with http://stackoverflow.com/a/7237286';
  var decodeShader = exports.decodeShader = '// TODO: compare with http://stackoverflow.com/a/7237286\n\nfloat @decode1(vec4 val){\n    vec4 scl = floor(255.0 * val + 0.5);\n    float sgn = (scl.a < 128.0) ? 1.0 : -1.0;\n    float exn = mod(scl.a * 2.0, 256.0) + floor(scl.b / 128.0) - 127.0;\n    float man = 1.0 +\n        (scl.r / 8388608.0) + \n        (scl.g / 32768.0) +\n        mod(scl.b, 128.0) / 128.0;\n    return sgn * man * pow(2.0, exn);\n}\n';
  
  function init(shape, format) {
    return {};
  }
  
  var tmp_float = new Float32Array(1),
      tmp_int = new Uint8Array(tmp_float.buffer);
  
  function encode(buf, value) {
    tmp_float[0] = value;
    buf.set(tmp_int, 0);
  }
  
  function decode(buf) {
    tmp_int.set(buf);
    return tmp_float[0];
  }
  
  },{}],10:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _index = require('./pack/stride/index.js');
  
  var pack_stride = _interopRequireWildcard(_index);
  
  var _index2 = require('./pack/tile/index.js');
  
  var pack_tile = _interopRequireWildcard(_index2);
  
  var _index3 = require('./codec/fixnum/index.js');
  
  var codec_fixnum = _interopRequireWildcard(_index3);
  
  var _index4 = require('./codec/softfloat/index.js');
  
  var codec_softfloat = _interopRequireWildcard(_index4);
  
  var _index5 = require('./activation/index.js');
  
  var _index6 = _interopRequireDefault(_index5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  
  exports.default = {
    pack: {
      stride: pack_stride,
      tile: pack_tile
    },
  
    read_shim: 'vec4 @read4(ivec4 pos){\n    int z = 4 * (pos.z / 4);\n    \n    if(@shape.z - z == 1){\n        return vec4(\n            @read(ivec4(pos.xy, z    , pos.w)), \n            0,\n            0,\n            0\n        );\n    }else if(@shape.z - z == 2){\n        return vec4(\n            @read(ivec4(pos.xy, z    , pos.w)), \n            @read(ivec4(pos.xy, z + 1, pos.w)),\n            0,\n            0\n        );\n    }else if(@shape.z - z == 3){\n        return vec4(\n            @read(ivec4(pos.xy, z    , pos.w)), \n            @read(ivec4(pos.xy, z + 1, pos.w)),\n            @read(ivec4(pos.xy, z + 2, pos.w)),\n            0\n        );\n    }\n    \n    return vec4(\n        @read(ivec4(pos.xy, z    , pos.w)),\n        @read(ivec4(pos.xy, z + 1, pos.w)),\n        @read(ivec4(pos.xy, z + 2, pos.w)),\n        @read(ivec4(pos.xy, z + 3, pos.w))\n    );\n}',
    write_shim: 'vec4 process4(ivec4 pos);\nfloat process(ivec4 pos){\n    return chsel(process4(ivec4(pos.xy, 4 * (pos.z / 4), pos.w)), imod(pos.z, 4));\n}',
  
    codec: {
      fixnum: codec_fixnum,
      softfloat: codec_softfloat
    },
    activations: _index6.default
  };
  
  },{"./activation/index.js":7,"./codec/fixnum/index.js":8,"./codec/softfloat/index.js":9,"./pack/stride/index.js":11,"./pack/tile/index.js":12}],11:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.writeShader = exports.readShader = undefined;
  exports.init = init;
  exports.pack = pack;
  exports.unpack = unpack;
  
  var _ndarray = require('ndarray');
  
  var _ndarray2 = _interopRequireDefault(_ndarray);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var readShader = exports.readShader = 'uniform sampler2D @tex;\nuniform ivec2 @texSize;\nuniform ivec4 @shape;\nuniform vec4 @stride;\n\n\nfloat @read(ivec4 pos){\n\tint tile = int(dot(vec4(pos), @stride));\n\treturn @decode1(texture2D(@tex,\n\t\t(vec2(0.5, 0.5) + vec2(tile2vec(tile, @texSize.x))) \n\t\t/ vec2(@texSize)));\n}';
  var writeShader = exports.writeShader = 'uniform ivec2 @texSize;\nuniform ivec4 @shape;\nuniform vec4 @stride;\n\n// vec4 clampify(vec4 v){\n//     return vec4(ivec4(clamp(v, vec4(0), vec4(1)) * 255.0)) / 255.0;\n// }\n\nfloat process(ivec4 pos);\nvoid main(){\n\tint tile = vec2tile(ivec2(gl_FragCoord.xy), @texSize.x);\n\tint chunks = @shape.x * @shape.y * @shape.z * @shape.w;\n\tif(tile >= chunks){ checkerboard(); return; }\n\n\tgl_FragColor = @encode1(@activation1(process(ivec4(\n\t\timod(tile, @shape.x),\n\t\timod(tile / @shape.x, @shape.y),\n\t\timod(tile / @shape.x / @shape.y, @shape.z ),\n\t\ttile / @shape.x / @shape.y / @shape.z\n\t))));\n}';
  
  function init(shape) {
      // var length = 4 * Math.ceil(shape[2] / 4) * shape[3] * shape[1] * shape[0];
      // var cols = Math.ceil(Math.sqrt(length) / 4) * 4;
  
      var length = shape[2] * shape[3] * shape[1] * shape[0];
      var cols = Math.ceil(Math.sqrt(length));
      var texSize = [cols, Math.ceil(length / cols)];
      return {
          texSize: texSize,
          shape: shape,
          // vec4(1, @shape.x, @shape.x * @shape.y, @shape.x * @shape.y * @shape.z)
          stride: [1, shape[0], shape[0] * shape[1], shape[0] * shape[1] * shape[2]]
      };
  }
  
  function pack(info, array, encode1, format) {
      // return Uint8Array or Float32Array
      array = (0, _ndarray2.default)(array.data, array.shape.concat([1, 1, 1, 1]).slice(0, 4), array.stride.concat([1, 1, 1, 1]).slice(0, 4), array.offset);
  
      var shape = info.shape;
      var length = info.texSize[0] * info.texSize[1] * 4;
  
      if (format.type === 'float32') {
          var data = new Float32Array(length);
      } else if (format.type === 'uint8') {
          var data = new Uint8Array(length);
      }
  
      for (var x = 0; x < shape[0]; x++) {
          for (var y = 0; y < shape[1]; y++) {
              for (var z = 0; z < shape[2]; z++) {
                  for (var w = 0; w < shape[3]; w++) {
                      var tile = x + y * shape[0] + z * shape[0] * shape[1] + w * shape[0] * shape[1] * shape[2];
  
                      encode1(data.subarray(4 * tile, 4 * tile + 4), array.get(x, y, z, w), info);
                  }
              }
          }
      }
  
      return data;
  }
  
  function unpack(info, data, decode1, type) {
      // if(type != 'float32') throw new Error('not impl');
  
      var shape = info.shape;
      var length = shape.reduce(function (a, b) {
          return a * b;
      });
  
      var array = (0, _ndarray2.default)(new Float32Array(length), shape.concat([1, 1, 1, 1]).slice(0, 4));
  
      for (var x = 0; x < shape[0]; x++) {
          for (var y = 0; y < shape[1]; y++) {
              for (var z = 0; z < shape[2]; z++) {
                  for (var w = 0; w < shape[3]; w++) {
                      var tile = x + y * shape[0] + z * shape[0] * shape[1] + w * shape[0] * shape[1] * shape[2];
  
                      array.set(x, y, z, w, decode1(data.subarray(4 * tile, 4 * tile + 4), info));
                  }
              }
          }
      }
      return array;
  }
  
  },{"ndarray":5}],12:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.writeShader = exports.readShader = undefined;
  exports.init = init;
  exports.pack = pack;
  exports.unpack = unpack;
  
  var _ndarray = require('ndarray');
  
  var _ndarray2 = _interopRequireDefault(_ndarray);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var readShader = exports.readShader = 'uniform sampler2D @tex;\nuniform ivec2 @texSize;\nuniform ivec4 @shape;\nuniform int @cols;\n\nfloat @read(ivec4 pos){\n    return @decode1(texture2D(@tex, (\n        vec2(tile2vec(\n            vec2tile(pos.zw, @shape.z)\n        , @cols) * ivec2(@shape.xy)) +\n        vec2(pos.xy) + vec2(0.5, 0.5)\n    ) / vec2(@texSize)));\n}\n';
  var writeShader = exports.writeShader = 'uniform ivec2 @texSize;\nuniform ivec4 @shape;\nuniform int @cols;\n\n// vec4 clampify(vec4 v){\n//     return vec4(ivec4(clamp(v, vec4(0), vec4(1)) * 255.0)) / 255.0;\n// }\n\nfloat process(ivec4 pos);\nvoid main(){\n    int tile = vec2tile(ivec2(gl_FragCoord.xy) / @shape.xy, @cols);\n    if(tile >= @shape.z * @shape.w){ checkerboard(); return; }\n\n    gl_FragColor = @encode1(@activation1(process(ivec4(\n    \timod(gl_FragCoord.x, @shape.x),\n    \timod(gl_FragCoord.y, @shape.y),\n        // mod(vec2(gl_FragCoord.xy), vec2(@shape.xy)), \n        tile2vec(tile, @shape.z)))));\n}';
  function init(shape) {
      var width = shape[0];
      // we pick the number of columns so we can keep
      // the texture as square as possible, with the
      // minimal amount of wasted space.
  
      var tiles = shape[2] * shape[3],
          cols = Math.max(1, Math.min(tiles, Math.ceil(Math.sqrt(shape[0] * shape[1] * tiles) / width)));
  
      var texSize = [width * cols, shape[1] * Math.ceil(tiles / cols)];
  
      return {
          texSize: texSize,
          cols: cols,
          shape: shape
      };
  }
  
  function pack(info, ndarray) {
      // return Uint8Array or Float32Array
  
  
      // uniform sampler2D @_tex;
      // uniform ivec2 @_texSize;
      // uniform ivec4 @_shape;
      // uniform int @_cols;
  
      // return {
      //  tex:
      //  texSize:
      //  shape:
      //  cols:
      // }
      throw new Error("not implemented: format/1-4/pack/tile/index.js:pack");
  }
  
  function unpack(info, arr) {
      // return ndarray
      throw new Error("not implemented: format/1-4/pack/tile/index.js:unpack");
  }
  
  },{"ndarray":5}],13:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.default = {
    hard_sigmoid: 'vec4 @activation4(vec4 data){\n    return clamp(data * vec4(0.2,0.2,0.2,0.2) + \n        vec4(.5,.5,.5,.5), vec4(0,0,0,0), vec4(1,1,1,1));\n}',
    linear: '#define @activation4 \n',
    relu: 'vec4 @activation4(vec4 data){\n    return max(data, vec4(0, 0, 0, 0));\n}\n',
    rgb: 'vec4 @activation4(vec4 data){\n    return data / 255.0; \n}',
    sigmoid: 'vec4 @activation4(vec4 data){\n    return (vec4(1,1,1,1)/(vec4(1,1,1,1) + exp(-2.0 * \n        clamp(data,vec4(-20,-20,-20,-20), vec4(20,20,20,20)) )));\n}\n',
    tanh: 'vec4 @activation4(vec4 data){\n    vec4 e = exp(2.0 * clamp(data, vec4(-20,-20,-20,-20), vec4(20,20,20,20)) );\n    return (e-vec4(1, 1, 1, 1))/(e+vec4(1, 1, 1, 1));\n}'
  };
  
  },{}],14:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.init = init;
  exports.encode = encode;
  exports.decode = decode;
  var encodeShader = exports.encodeShader = 'uniform vec2 @range;\n\nvec4 @encode4(vec4 v){\n\treturn (v - vec4(@range.x)) / vec4(@range.y - @range.x);\n}';
  var decodeShader = exports.decodeShader = 'uniform vec2 @range;\n\nvec4 @decode4(vec4 v){\n\treturn v * vec4(@range.y - @range.x) + vec4(@range.x);\n}';
  
  function init(shape, format) {
    return {
      range: [isFinite(format.min) ? format.min : 0, isFinite(format.max) ? format.max : 1]
      // max: ,
      // min: ,
    };
  }
  
  function encode(data, r, g, b, a, info) {
  
    data[0] = Math.round(255 * Math.min(1, Math.max(0, (r - info.range[0]) / (info.range[1] - info.range[0]))));
    data[1] = Math.round(255 * Math.min(1, Math.max(0, (g - info.range[0]) / (info.range[1] - info.range[0]))));
    data[2] = Math.round(255 * Math.min(1, Math.max(0, (b - info.range[0]) / (info.range[1] - info.range[0]))));
    data[3] = Math.round(255 * Math.min(1, Math.max(0, (a - info.range[0]) / (info.range[1] - info.range[0]))));
    // console.log(data[0], data[1], data[2])
  }
  
  function decode(data, r, g, b, a, info) {
    data[0] = r / 255 * (info.range[1] - info.range[0]) + info.range[0];
    data[1] = g / 255 * (info.range[1] - info.range[0]) + info.range[0];
    data[2] = b / 255 * (info.range[1] - info.range[0]) + info.range[0];
    data[3] = a / 255 * (info.range[1] - info.range[0]) + info.range[0];
  }
  
  },{}],15:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.init = init;
  exports.encode = encode;
  exports.decode = decode;
  var encodeShader = exports.encodeShader = '#define @encode4 \n ';
  var decodeShader = exports.decodeShader = '#define @decode4 \n';
  
  function init(shape, format) {
    return {};
  }
  
  function encode(data, r, g, b, a) {
    data[0] = r;
    data[1] = g;
    data[2] = b;
    data[3] = a;
  }
  
  function decode(data, r, g, b, a) {
    data[0] = r;
    data[1] = g;
    data[2] = b;
    data[3] = a;
  }
  
  },{}],16:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _index = require('./pack/stride/index.js');
  
  var pack_stride = _interopRequireWildcard(_index);
  
  var _index2 = require('./pack/tile/index.js');
  
  var pack_tile = _interopRequireWildcard(_index2);
  
  var _index3 = require('./codec/raw/index.js');
  
  var codec_raw = _interopRequireWildcard(_index3);
  
  var _index4 = require('./codec/linquant/index.js');
  
  var codec_linquant = _interopRequireWildcard(_index4);
  
  var _index5 = require('./activation/index.js');
  
  var _index6 = _interopRequireDefault(_index5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  
  exports.default = {
    pack: {
      stride: pack_stride,
      tile: pack_tile
    },
  
    read_shim: 'float @read(ivec4 pos){\n    return chsel(@read4(pos), imod(pos.z, 4));\n}\n',
    write_shim: 'float process(ivec4 pos);\nvec4 process4(ivec4 pos){\n    int z = 4 * (pos.z / 4);\n\n    if(@shape.z - z == 1){\n        return vec4(\n            process(ivec4(pos.xy, z    , pos.w)), \n            0,\n            0,\n            0\n        );\n    }else if(@shape.z - z == 2){\n        return vec4(\n            process(ivec4(pos.xy, z    , pos.w)), \n            process(ivec4(pos.xy, z + 1, pos.w)),\n            0,\n            0\n        );\n    }else if(@shape.z - z == 3){\n        return vec4(\n            process(ivec4(pos.xy, z    , pos.w)), \n            process(ivec4(pos.xy, z + 1, pos.w)),\n            process(ivec4(pos.xy, z + 2, pos.w)),\n            0\n        );\n    }\n    \n    return vec4(\n        process(ivec4(pos.xy, z    , pos.w)),\n        process(ivec4(pos.xy, z + 1, pos.w)),\n        process(ivec4(pos.xy, z + 2, pos.w)),\n        process(ivec4(pos.xy, z + 3, pos.w))\n    );\n}',
  
    codec: {
      raw: codec_raw,
      linquant: codec_linquant
    },
    activations: _index6.default
  };
  
  },{"./activation/index.js":13,"./codec/linquant/index.js":14,"./codec/raw/index.js":15,"./pack/stride/index.js":17,"./pack/tile/index.js":18}],17:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.writeShader = exports.readShader = undefined;
  
  var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
  
  exports.init = init;
  exports.pack = pack;
  exports.unpack = unpack;
  
  var _ndarray = require('ndarray');
  
  var _ndarray2 = _interopRequireDefault(_ndarray);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var readShader = exports.readShader = 'uniform sampler2D @tex;\nuniform ivec2 @texSize;\nuniform ivec4 @shape;\nuniform vec4 @stride;\n\n\nvec4 @read4(ivec4 pos){\n\tint tile = int(dot(vec4(pos), @stride));\n\treturn @decode4(texture2D(@tex,\n\t\t(vec2(0.5, 0.5) + vec2(tile2vec(tile, @texSize.x))) \n\t\t/ vec2(@texSize)));\n}';
  var writeShader = exports.writeShader = 'uniform ivec2 @texSize;\nuniform ivec4 @shape;\nuniform vec4 @stride;\n\nvec4 process4(ivec4 pos);\nvoid main(){\n\tint tile = @texSize.x * int(gl_FragCoord.y) + int(gl_FragCoord.x);\n\tint shapez = ceildiv(@shape.z, 4);\n\tif(tile >= int(@stride.w) * @shape.w){ checkerboard(); return; }\n\n\tgl_FragColor = @encode4(@activation4(process4(ivec4(\n\t\timod(tile, @shape.x),\n\t\timod(tile / @shape.x, @shape.y),\n\t\t4 * imod(tile / @shape.x / @shape.y, shapez),\n\t\ttile / @shape.x / @shape.y / shapez\n\t))));\n}\n';
  function init(shape) {
      var length = Math.ceil(shape[2] / 4) * shape[3] * shape[1] * shape[0];
      var cols = Math.ceil(Math.sqrt(length));
      var texSize = [cols, Math.ceil(length / cols)];
  
      console.assert(texSize[0] * texSize[1] >= length);
      return {
          texSize: texSize,
          shape: shape,
  
          stride: [1, shape[0], shape[0] * shape[1] / 4, // the /4 is because of the color channel
          shape[0] * shape[1] * Math.ceil(shape[2] / 4)]
      };
  }
  
  function pack(info, array, encode4, format) {
      // return Uint8Array or Float32Array
  
      array = (0, _ndarray2.default)(array.data, array.shape.concat([1, 1, 1, 1]).slice(0, 4), array.stride.concat([1, 1, 1, 1]).slice(0, 4), array.offset);
  
      var _info$texSize = _slicedToArray(info.texSize, 2),
          width = _info$texSize[0],
          height = _info$texSize[1],
          length = width * height * 4;
  
      var shape = info.shape;
  
      if (format.type === 'float32') {
          var data = new Float32Array(length);
      } else if (format.type === 'uint8') {
          var data = new Uint8Array(length);
      }
  
      var chans = Math.ceil(info.shape[2] / 4);
  
      for (var i = 0; i < info.shape[0]; i++) {
          for (var j = 0; j < info.shape[1]; j++) {
              for (var k = 0; k < chans; k++) {
                  var b = Math.min(k * 4 + 4, shape[2]) - k * 4;
                  for (var w = 0; w < info.shape[3]; w++) {
  
                      var tile = i + j * shape[0] + k * shape[0] * shape[1] + w * shape[0] * shape[1] * chans;
  
                      var pos = 4 * tile;
                      encode4(data.subarray(pos, pos + 4), b < 1 ? 0 : array.get(i, j, 4 * k + 0, w), b < 2 ? 0 : array.get(i, j, 4 * k + 1, w), b < 3 ? 0 : array.get(i, j, 4 * k + 2, w), b < 4 ? 0 : array.get(i, j, 4 * k + 3, w), info);
                  }
              }
          }
      }
  
      return data;
  }
  
  function unpack(info, data, decode4, type) {
  
      var shape = info.shape;
      var shapelength = shape.reduce(function (a, b) {
          return a * b;
      });
  
      var _info$texSize2 = _slicedToArray(info.texSize, 2),
          width = _info$texSize2[0],
          height = _info$texSize2[1],
          length = width * height * 4;
  
      var chans = Math.ceil(info.shape[2] / 4);
  
      // if(type === 'float32'){
      var array = (0, _ndarray2.default)(new Float32Array(shapelength), shape);
      var buf = new Float32Array(4);
      // }else if(type == 'uint8'){
      //     var array = ndarray(new Uint8Array(shapelength), shape)
      //     var buf = new Uint8Array(4);
      // }else throw new Error('unimplemented type');
  
  
      for (var i = 0; i < info.shape[0]; i++) {
          for (var j = 0; j < info.shape[1]; j++) {
              for (var k = 0; k < chans; k++) {
                  var b = Math.min(k * 4 + 4, shape[2]) - k * 4;
                  for (var w = 0; w < info.shape[3]; w++) {
  
                      var tile = i + j * shape[0] + k * shape[0] * shape[1] + w * shape[0] * shape[1] * chans;
  
                      decode4(buf, data[4 * tile + 0], data[4 * tile + 1], data[4 * tile + 2], data[4 * tile + 3], info);
  
                      for (var x = 0; x < b; x++) {
                          array.set(i, j, 4 * k + x, w, buf[x]);
                      }
                  }
              }
          }
      }
  
      return array;
  }
  
  },{"ndarray":5}],18:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.writeShader = exports.readShader = undefined;
  
  var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
  
  exports.init = init;
  exports.pack = pack;
  exports.unpack = unpack;
  
  var _ndarray = require('ndarray');
  
  var _ndarray2 = _interopRequireDefault(_ndarray);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var readShader = exports.readShader = 'uniform sampler2D @tex;\nuniform ivec2 @texSize;\nuniform ivec4 @shape;\nuniform int @cols;\n\n\nvec4 @read4(ivec4 pos){\n\tfloat tile = float(vec2tile(pos.zw / ivec2(4, 1), ceildiv(@shape.z, 4)));\n    return @decode4(texture2D(@tex, (\n        vec2(\n        \tmod(tile, float(@cols)),\n        \tfloor(tile / float(@cols))\n        ) * vec2(@shape.xy) +\n        vec2(pos.xy) + vec2(0.5, 0.5)\n    ) / vec2(@texSize)));\n}\n';
  var writeShader = exports.writeShader = 'uniform ivec2 @texSize;\nuniform ivec4 @shape;\nuniform int @cols;\n\nvec4 process4(ivec4 pos);\nvoid main(){\n    int tile = vec2tile(ivec2(gl_FragCoord.xy) / @shape.xy, @cols);\n    int chunks = ceildiv(@shape.z, 4);\n    if(tile * 4 >= @shape.z * @shape.w){ checkerboard(); return; }\n    gl_FragColor = @encode4(@activation4(process4(ivec4(\n        mod(gl_FragCoord.xy, vec2(@shape.xy)), \n        tile2vec(tile, chunks) * ivec2(4, 1)))));\n}\n\n';
  
  function init(shape) {
      var width = shape[0]; // var width = shape[0] * 4;    
      // we pick the number of columns so we can keep
      // the texture as square as possible, with the
      // minimal amount of wasted space.
  
      var tiles = Math.ceil(shape[2] / 4) * shape[3],
          cols = Math.max(1, Math.min(tiles, Math.round(Math.sqrt(shape[0] * shape[1] * tiles) / width)));
  
      var texSize = [width * cols, shape[1] * Math.ceil(tiles / cols)];
  
      return {
          texSize: texSize,
          cols: cols,
          shape: shape
      };
  }
  
  function pack(info, array, encode4, format) {
      array = (0, _ndarray2.default)(array.data, array.shape.concat([1, 1, 1, 1]).slice(0, 4), array.stride.concat([1, 1, 1, 1]).slice(0, 4), array.offset);
  
      var shape = array.shape,
          tiles = Math.ceil(shape[2] / 4) * shape[3],
          tw = shape[0],
          th = shape[1],
          cols = info.cols,
          _info$texSize = _slicedToArray(info.texSize, 2),
          width = _info$texSize[0],
          height = _info$texSize[1],
          chunks = Math.ceil(shape[2] / 4),
          length = width * height * 4;
  
  
      if (format.type === 'float32') {
          var data = new Float32Array(length);
      } else if (format.type === 'uint8') {
          var data = new Uint8Array(length);
      }
  
      for (var z = 0; z < chunks; z++) {
          for (var w = 0; w < shape[3]; w++) {
              var tile = w * chunks + z;
              var b = Math.min(z * 4 + 4, shape[2]) - z * 4;
  
              var ih = th * Math.floor(tile / cols);
              var jw = tw * (tile % cols);
  
              for (var i = 0; i < tw; i++) {
                  for (var j = 0; j < th; j++) {
  
                      var pos = 4 * ((ih + j) * width + jw + i);
                      encode4(data.subarray(pos, pos + 4), b < 1 ? 0 : array.get(i, j, 4 * z + 0, w), b < 2 ? 0 : array.get(i, j, 4 * z + 1, w), b < 3 ? 0 : array.get(i, j, 4 * z + 2, w), b < 4 ? 0 : array.get(i, j, 4 * z + 3, w), info);
                  }
              }
          }
      }
      return data;
  }
  
  function unpack(info, data, decode4, type) {
      // throw new Error("not implemented: format/4-4/pack/tile/index.js:unpack")
  
      var shapelength = info.shape.reduce(function (a, b) {
          return a * b;
      });
      var array = (0, _ndarray2.default)(new Float32Array(shapelength), info.shape);
  
      var shape = array.shape,
          tiles = Math.ceil(shape[2] / 4) * shape[3],
          tw = shape[0],
          th = shape[1],
          cols = info.cols,
          _info$texSize2 = _slicedToArray(info.texSize, 2),
          width = _info$texSize2[0],
          height = _info$texSize2[1],
          chunks = Math.ceil(shape[2] / 4),
          length = width * height * 4;
  
      // if(format.type === 'float32'){
      //     var data = new Float32Array(length);    
      // }else if(format.type === 'uint8'){
      //     var data = new Uint8Array(length);    
      // }
  
      var buf = new Float32Array(4);
  
      for (var z = 0; z < chunks; z++) {
          for (var w = 0; w < shape[3]; w++) {
              var tile = w * chunks + z;
              var b = Math.min(z * 4 + 4, shape[2]) - z * 4;
  
              var ih = th * Math.floor(tile / cols);
              var jw = tw * (tile % cols);
  
              for (var i = 0; i < tw; i++) {
                  for (var j = 0; j < th; j++) {
  
                      var pos = 4 * ((ih + j) * width + jw + i);
                      // encode4(
                      //     data.subarray(pos, pos + 4),
                      //     b < 1 ? 0 : array.get(i, j, 4*z+0, w), 
                      //     b < 2 ? 0 : array.get(i, j, 4*z+1, w), 
                      //     b < 3 ? 0 : array.get(i, j, 4*z+2, w), 
                      //     b < 4 ? 0 : array.get(i, j, 4*z+3, w), info)
  
                      decode4(buf, data[pos], data[pos + 1], data[pos + 2], data[pos + 3], info);
  
                      if (b >= 1) array.set(i, j, 4 * z + 0, w, buf[0]);
                      if (b >= 2) array.set(i, j, 4 * z + 1, w, buf[1]);
                      if (b >= 3) array.set(i, j, 4 * z + 2, w, buf[2]);
                      if (b >= 4) array.set(i, j, 4 * z + 3, w, buf[3]);
                  }
              }
          }
      }
      return array;
  }
  
  },{"ndarray":5}],19:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _index = require('./4-4/index.js');
  
  var _index2 = _interopRequireDefault(_index);
  
  var _index3 = require('./1-4/index.js');
  
  var _index4 = _interopRequireDefault(_index3);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  exports.default = {
    '4:4': _index2.default,
    '1:4': _index4.default
  };
  
  },{"./1-4/index.js":10,"./4-4/index.js":16}],20:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _index = require('./tensor/index.js');
  
  Object.defineProperty(exports, 'Tensor', {
    enumerable: true,
    get: function get() {
      return _index.Tensor;
    }
  });
  Object.defineProperty(exports, 'OutputTensor', {
    enumerable: true,
    get: function get() {
      return _index.OutputTensor;
    }
  });
  Object.defineProperty(exports, 'InPlaceTensor', {
    enumerable: true,
    get: function get() {
      return _index.InPlaceTensor;
    }
  });
  
  var _index2 = require('./runtime/index.js');
  
  Object.defineProperty(exports, 'Run', {
    enumerable: true,
    get: function get() {
      return _index2.Run;
    }
  });
  Object.defineProperty(exports, 'Compile', {
    enumerable: true,
    get: function get() {
      return _index2.Compile;
    }
  });
  
  var _util = require('./util.js');
  
  Object.defineProperty(exports, 'createGL', {
    enumerable: true,
    get: function get() {
      return _util.createGL;
    }
  });
  
  },{"./runtime/index.js":23,"./tensor/index.js":30,"./util.js":32}],21:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.checkLinkError = checkLinkError;
  exports.checkShaderError = checkShaderError;
  exports.checkFramebufferError = checkFramebufferError;
  // code for pretty printing shader errors from regl
  
  function checkLinkError(gl, program, fragShader, vertShader, command) {
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
          var errLog = gl.getProgramInfoLog(program);
          var fragParse = parseSource(fragShader, command);
          var vertParse = parseSource(vertShader, command);
  
          var header = 'Error linking program with vertex shader, "' + vertParse[0].name + '", and fragment shader "' + fragParse[0].name + '"';
  
          if (typeof document !== 'undefined') {
              console.log('%c' + header + '\n%c' + errLog, 'color:red;text-decoration:underline;font-weight:bold', 'color:red');
          } else {
              console.log(header + '\n' + errLog);
          }
  
          console.log(fragShader);
  
          throw new Error(header);
      }
  }
  
  function checkShaderError(gl, shader, source, type, command) {
      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
          var errLog = gl.getShaderInfoLog(shader);
          var typeName = type === gl.FRAGMENT_SHADER ? 'fragment' : 'vertex';
          // checkCommandType(source, 'string', typeName + ' shader source must be a string', command)
  
          var files = parseSource(source, command);
          var errors = parseErrorLog(errLog);
          annotateFiles(files, errors);
  
          Object.keys(files).forEach(function (fileNumber) {
              var file = files[fileNumber];
              if (!file.hasErrors) {
                  return;
              }
  
              var strings = [''];
              var styles = [''];
  
              function push(str, style) {
                  strings.push(str);
                  styles.push(style || '');
              }
  
              push('file number ' + fileNumber + ': ' + file.name + '\n', 'color:red;text-decoration:underline;font-weight:bold');
  
              file.lines.forEach(function (line) {
                  if (line.errors.length > 0) {
                      push(leftPad(line.number, 4) + '|  ', 'background-color:yellow; font-weight:bold');
                      push(line.line + '\n', 'color:red; background-color:yellow; font-weight:bold');
  
                      // try to guess token
                      var offset = 0;
                      line.errors.forEach(function (error) {
                          var message = error.message;
                          var token = /^\s*\'(.*)\'\s*\:\s*(.*)$/.exec(message);
                          if (token) {
                              var tokenPat = token[1];
                              message = token[2];
                              switch (tokenPat) {
                                  case 'assign':
                                      tokenPat = '=';
                                      break;
                              }
                              offset = Math.max(line.line.indexOf(tokenPat, offset), 0);
                          } else {
                              offset = 0;
                          }
  
                          push(leftPad('| ', 6));
                          push(leftPad('^^^', offset + 3) + '\n', 'font-weight:bold');
                          push(leftPad('| ', 6));
                          push(message + '\n', 'font-weight:bold');
                      });
                      push(leftPad('| ', 6) + '\n');
                  } else {
                      push(leftPad(line.number, 4) + '|  ');
                      push(line.line + '\n', 'color:red');
                  }
              });
              if (typeof document !== 'undefined') {
                  styles[0] = strings.join('%c');
                  console.log.apply(console, styles);
              } else {
                  console.log(strings.join(''));
              }
          });
  
          throw new Error('Error compiling ' + typeName + ' shader, ' + files[0].name);
      }
  }
  
  function checkFramebufferError(gl) {
  
      var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
      if (status != gl.FRAMEBUFFER_COMPLETE) {
          var statusCode = {};
          statusCode[gl.FRAMEBUFFER_COMPLETE] = 'complete';
          statusCode[gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT] = 'incomplete attachment';
          statusCode[gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS] = 'incomplete dimensions';
          statusCode[gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT] = 'incomplete, missing attachment';
          statusCode[gl.FRAMEBUFFER_UNSUPPORTED] = 'unsupported';
          throw new Error('framebuffer configuration not supported, status = ' + statusCode[status]);
      }
  }
  
  function leftPad(str, n) {
      str = str + '';
      while (str.length < n) {
          str = ' ' + str;
      }
      return str;
  }
  
  function ShaderFile() {
      this.name = 'unknown';
      this.lines = [];
      this.index = {};
      this.hasErrors = false;
  }
  
  function ShaderLine(number, line) {
      this.number = number;
      this.line = line;
      this.errors = [];
  }
  
  function ShaderError(fileNumber, lineNumber, message) {
      this.file = fileNumber;
      this.line = lineNumber;
      this.message = message;
  }
  
  function parseSource(source, command) {
      var lines = source.split('\n');
      var lineNumber = 1;
      var fileNumber = 0;
      var files = {
          unknown: new ShaderFile(),
          0: new ShaderFile()
      };
      files.unknown.name = files[0].name = 'unknown';
      files.unknown.lines.push(new ShaderLine(0, ''));
      for (var i = 0; i < lines.length; ++i) {
          var line = lines[i];
          var parts = /^\s*\#\s*(\w+)\s+(.+)\s*$/.exec(line);
          if (parts) {
              switch (parts[1]) {
                  case 'line':
                      var lineNumberInfo = /(\d+)(\s+\d+)?/.exec(parts[2]);
                      if (lineNumberInfo) {
                          lineNumber = lineNumberInfo[1] | 0;
                          if (lineNumberInfo[2]) {
                              fileNumber = lineNumberInfo[2] | 0;
                              if (!(fileNumber in files)) {
                                  files[fileNumber] = new ShaderFile();
                              }
                          }
                      }
                      break;
                  case 'define':
                      var nameInfo = /SHADER_NAME(_B64)?\s+(.*)$/.exec(parts[2]);
                      if (nameInfo) {
                          files[fileNumber].name = nameInfo[1] ? decodeB64(nameInfo[2]) : nameInfo[2];
                      }
                      break;
              }
          }
          files[fileNumber].lines.push(new ShaderLine(lineNumber++, line));
      }
      Object.keys(files).forEach(function (fileNumber) {
          var file = files[fileNumber];
          file.lines.forEach(function (line) {
              file.index[line.number] = line;
          });
      });
      return files;
  }
  
  function parseErrorLog(errLog) {
      var result = [];
      errLog.split('\n').forEach(function (errMsg) {
          if (errMsg.length < 5) {
              return;
          }
          var parts = /^ERROR\:\s+(\d+)\:(\d+)\:\s*(.*)$/.exec(errMsg);
          if (parts) {
              result.push(new ShaderError(parts[1] | 0, parts[2] | 0, parts[3].trim()));
          } else if (errMsg.length > 0) {
              result.push(new ShaderError('unknown', 0, errMsg));
          }
      });
      return result;
  }
  
  function annotateFiles(files, errors) {
      errors.forEach(function (error) {
          var file = files[error.file];
          if (file) {
              var line = file.index[error.line];
              if (line) {
                  line.errors.push(error);
                  file.hasErrors = true;
                  return;
              }
          }
          files.unknown.hasErrors = true;
          files.unknown.lines[0].errors.push(error);
      });
  }
  
  },{}],22:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.default = assembleFragmentShader;
  
  var _base = require('../tensor/base.js');
  
  var _base2 = _interopRequireDefault(_base);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var TENSOR_FRAGMENT_HEADER = 'precision highp int;\nprecision highp float;\n\nint   imod(int f, int p){ return f - p * (f / p); }\nint   vec2tile(ivec2 v, int rows){ return rows * v.y + v.x; }\nivec2 tile2vec(int f, int rows){ return ivec2(imod(f, rows), f / rows); }\nint   ceildiv(int a, int b){ return (a - 1) / b + 1; }\nvoid  checkerboard(){ gl_FragColor = vec4(mod(gl_FragCoord.x - gl_FragCoord.y, 2.0), 0.2, 0.1, 1); }\n\nfloat chsel(vec4 val, int ch){\n\tif(ch == 0) return val.r;\n\tif(ch == 1) return val.g;\n\tif(ch == 2) return val.b;\n\treturn val.a;\n}\n'; // import { Tensor, OutputTensor, InPlaceTensor } from '../tensor/index.js'
  function assembleFragmentShader(shaderGen, output, uniforms) {
      var tensorShader = shaderGen(uniforms, output);
  
      var fragmentShader = TENSOR_FRAGMENT_HEADER;
      for (var uniform in uniforms) {
          if (uniforms[uniform] instanceof _base2.default) {
              var tensor = uniforms[uniform];
  
              fragmentShader += tensor._format.codec.decodeShader.replace(/@/g, uniform + '_') + '\n';
              fragmentShader += tensor._format.pack.readShader.replace(/@/g, uniform + '_') + '\n';
  
              if (tensor.format.density == '1:4' && new RegExp(uniform + '_read4\\b').test(tensorShader) || tensor.format.density == '4:4' && new RegExp(uniform + '_read\\b').test(tensorShader)) {
                  fragmentShader += tensor._format.read_shim.replace(/@/g, uniform + '_') + '\n';
              }
          }
      }
  
      var activation = typeof uniforms._activation == 'string' && uniforms._activation != 'linear' ? uniforms._activation.toLowerCase() : 'linear';
  
      if (!(activation in output._format.activations)) throw new Error('Unknown activation type ' + activation);
  
      fragmentShader += output._format.activations[activation].replace(/@/g, 'out_') + '\n';
      fragmentShader += output._format.codec.encodeShader.replace(/@/g, 'out_') + '\n';
      fragmentShader += output._format.pack.writeShader.replace(/@/g, 'out_') + '\n';
  
      if (output.format.density == '1:4' && /process4\b/.test(tensorShader) || output.format.density == '4:4' && /process\b/.test(tensorShader)) {
          fragmentShader += output._format.write_shim.replace(/@/g, 'out_') + '\n';
      }
  
      fragmentShader += tensorShader.replace(/@/g, 'out_');
  
      // console.log(fragmentShader)
  
      return fragmentShader;
  }
  
  },{"../tensor/base.js":27}],23:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.Compile = Compile;
  exports.Run = Run;
  
  var _program = require('./program.js');
  
  var _program2 = _interopRequireDefault(_program);
  
  var _frag = require('./frag.js');
  
  var _frag2 = _interopRequireDefault(_frag);
  
  var _index = require('../tensor/index.js');
  
  var _check = require('./check.js');
  
  var _tnsl = require('./tnsl.js');
  
  var _tnsl2 = _interopRequireDefault(_tnsl);
  
  var _timer = require('./timer.js');
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function Compile(shaderGen, output) {
      var uniforms = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  
      var startTime = (0, _timer.now)();
      if (!(output instanceof _index.OutputTensor)) throw new Error("First argument must be an instance of OutputTensor");
  
      if (typeof shaderGen === 'string') shaderGen = (0, _tnsl2.default)(shaderGen);
  
      var gl = output.gl;
      var program = (0, _program2.default)(gl, (0, _frag2.default)(shaderGen, output, uniforms));
      var compileTime = (0, _timer.now)() - startTime;
      // console.log('Compile Time', compileTime)
      return program;
  }
  
  function Run(shaderGen, output) {
      var uniforms = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
      var callback = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
  
      var tp = Compile(shaderGen, output, uniforms);
  
      var gl = output.gl;
  
      if (callback && typeof callback != 'function') throw new Error('Callback must be a function');
      if (callback) {
          (0, _timer.beginTimer)(gl, {
              shader: shaderGen,
              output: output
          });
      }
  
      gl.useProgram(tp.program);
      gl.disable(gl.DEPTH_TEST);
      gl.disable(gl.BLEND);
  
      var setUniform = tp.setUniform,
          texIndex = 0,
          mustSwap = false;
  
      for (var name in uniforms) {
          if (name.startsWith('_')) continue;
  
          if (name + '_tex' in tp.uniformTypes) {
              var tensor = uniforms[name];
              if (tensor.gl !== output.gl) throw new Error('Uniforms must belong to same GL context as output');
              if (tensor === output) mustSwap = true;
  
              for (var uniform in tensor.info) {
                  setUniform(name + '_' + uniform, tensor.info[uniform]);
              }
  
              gl.activeTexture(gl['TEXTURE' + texIndex]);
              gl.bindTexture(gl.TEXTURE_2D, tensor.tex);
              setUniform(name + '_tex', texIndex);
  
              texIndex++;
          } else if (name in tp.uniformTypes) {
              setUniform(name, uniforms[name]);
          } else {
              throw new Error("Unknown uniform " + name);
          }
      }
  
      // Ordinarily we can't write to the same texture that we're using as
      // an input, as this could lead to all sorts of terrible race conditions,
      // undefined behavior, and invalid state. InPlaceTensors actually consist
      // of a pair of textures which are swapped for these in-place operations. 
      if (mustSwap) output.swap();
  
      for (var _uniform in output.info) {
          setUniform('out_' + _uniform, output.info[_uniform]);
      }
  
      gl.bindFramebuffer(gl.FRAMEBUFFER, output.fbo);
      gl.viewport(0, 0, output.info.texSize[0], output.info.texSize[1]);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // draw to framebuffer
  
      (0, _check.checkFramebufferError)(gl);
  
      // var runTime = now() - startTime;
      // timer.end()
      if (callback) {
          (0, _timer.endTimer)(gl, function (info) {
              // console.log('GPU time: ', info)
              callback(info);
          });
      }
      // console.log('CPU Run Time', runTime)
  
      return output;
  }
  
  },{"../tensor/index.js":30,"./check.js":21,"./frag.js":22,"./program.js":24,"./timer.js":25,"./tnsl.js":26}],24:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.default = getTensorProgram;
  exports.bindAttributeBuffer = bindAttributeBuffer;
  exports.createShaderProgram = createShaderProgram;
  
  var _check = require('./check.js');
  
  var TENSOR_VERTEX_SHADER = '\n    precision highp float;\n    attribute vec2 a_position;\n    void main() {\n        gl_Position = vec4(a_position, 0, 1);\n    }\n';
  
  var UNIFORM_SETTERS = { vec4: '4fv', vec3: '3fv', vec2: '2fv', float: '1f',
      ivec4: '4iv', ivec3: '3iv', ivec2: '2iv', int: '1i',
      sampler2D: '1i' };
  
  function getTensorProgram(gl, fragmentShader) {
      if (!gl._tensorPrograms) gl._tensorPrograms = {};
      if (fragmentShader in gl._tensorPrograms) {
          return gl._tensorPrograms[fragmentShader];
      }
      var program = createTensorProgram(gl, fragmentShader);
      gl._tensorPrograms[fragmentShader] = program;
      return program;
  }
  
  function createTensorProgram(gl, fragmentShader) {
      var program = createShaderProgram(gl, TENSOR_VERTEX_SHADER, fragmentShader);
  
      gl.useProgram(program);
      bindAttributeBuffer(gl, program);
  
      var uniformTypes = extractUniformDeclarations(fragmentShader),
          uniformLocs = {};
  
      function addUniform(name, type) {
          uniformLocs[name] = { loc: gl.getUniformLocation(program, name), type: type };
      }
  
      for (var name in uniformTypes) {
          var type = uniformTypes[name];
          if (type in UNIFORM_SETTERS) {
              addUniform(name, type);
          } else throw new Error("Unknown uniform type " + type);
      }
  
      function setUniform(name, value) {
          if (!(name in uniformLocs)) {
              throw new Error("Could not find uniform " + name);
          }
          gl['uniform' + UNIFORM_SETTERS[uniformLocs[name].type]](uniformLocs[name].loc, value);
      }
  
      return {
          program: program,
          fragmentShader: fragmentShader,
          uniformLocs: uniformLocs,
          uniformTypes: uniformTypes,
          setUniform: setUniform
      };
  }
  
  function bindAttributeBuffer(gl, program) {
      gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
  
      var positionLocation = gl.getAttribLocation(program, "a_position");
      gl.enableVertexAttribArray(positionLocation);
      gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
  }
  
  function extractUniformDeclarations(str) {
      var uniforms = {};
      str = str.replace(/((?:\/\*(?:[^*]|(?:\*+[^*\/]))*\*+\/)|(?:\/\/.*))/g, '');
      str = str.replace(/\/\/.*\n/g, '');
      var m,
          re = /uniform\s*([\w_]+)\s*([\w_]+)/g;
      while (m = re.exec(str)) {
          uniforms[m[2]] = m[1];
      }return uniforms;
  }
  
  function createShaderProgram(gl, vertexSource, fragmentSource) {
      var vertexShader = compileShader(gl, vertexSource, gl.VERTEX_SHADER);
      var fragmentShader = compileShader(gl, fragmentSource, gl.FRAGMENT_SHADER);
  
      // var debug = gl.getExtension('WEBGL_debug_shaders')
      // console.log(debug.getTranslatedShaderSource(vertexShader));
      // console.log(debug.getTranslatedShaderSource(fragmentShader));
  
      var program = gl.createProgram();
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
  
      // interestingly enough it seems like Safari never emits
      // a shader program link error. 
      (0, _check.checkLinkError)(gl, program, fragmentSource, vertexSource);
  
      return program;
  }
  
  function compileShader(gl, shaderSource, shaderType) {
      var shader = gl.createShader(shaderType);
      gl.shaderSource(shader, shaderSource);
      gl.compileShader(shader);
      var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
      (0, _check.checkShaderError)(gl, shader, shaderSource, shaderType);
      return shader;
  }
  
  },{"./check.js":21}],25:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.now = now;
  exports.beginTimer = beginTimer;
  exports.endTimer = endTimer;
  function now() {
    if (typeof performance === 'undefined') {
      return Date.now();
    } else {
      return performance.now();
    }
  }
  
  function getTimer(gl) {
    if (gl.NO_PROFILE) return;
    if (typeof gl.TIMER_POOL === 'undefined') {
      var extTimer = gl.getExtension('ext_disjoint_timer_query');
      if (!extTimer || !extTimer.createQueryEXT) {
        gl.NO_PROFILE = true;
        return;
      }
      gl.TIMER_POOL = createTimer(gl);
    }
    return gl.TIMER_POOL;
  }
  
  function beginTimer(gl) {
    var info = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  
    var timer = getTimer(gl);
    if (timer) {
      timer.begin(info);
    }
  }
  
  function endTimer(gl, callback) {
    var timer = getTimer(gl);
    if (timer) {
      timer.end(callback);
    } else if (callback) {
      console.warn("Browser does not support ext_disjoint_timer_query, triggering callback after fixed timeout.");
      setTimeout(callback, 100);
    }
  }
  
  function createTimer(gl) {
    var extTimer = gl.getExtension('ext_disjoint_timer_query');
  
    var queryPool = [];
    function allocQuery() {
      return queryPool.pop() || extTimer.createQueryEXT();
    }
    function freeQuery(query) {
      queryPool.push(query);
    }
  
    var pendingQueries = [];
    function beginQuery(info) {
      var query = allocQuery();
      extTimer.beginQueryEXT(extTimer.TIME_ELAPSED_EXT, query);
      pendingQueries.push([query, info]);
    }
  
    function endQuery() {
      extTimer.endQueryEXT(extTimer.TIME_ELAPSED_EXT);
    }
  
    function callback(info, time) {
      var fn = info.callback;
      info.gpuTime = time;
      delete info.callback;
      if (fn) fn(info);
    }
  
    function monitorPending() {
      for (var i = 0; i < pendingQueries.length; ++i) {
        var query = pendingQueries[i][0];
        if (extTimer.getQueryObjectEXT(query, extTimer.QUERY_RESULT_AVAILABLE_EXT)) {
          var queryTime = extTimer.getQueryObjectEXT(query, extTimer.QUERY_RESULT_EXT);
          callback(pendingQueries[i][1], queryTime / 1e6);
          freeQuery(query);
          pendingQueries.splice(i, 1);
          i--;
        }
      }
    }
  
    var isPolling = false;
    function loop() {
      if (pendingQueries.length > 0) {
        monitorPending();
        requestAnimationFrame(loop);
      } else {
        isPolling = false;
      }
    }
  
    var currentInfo = null;
    return {
      begin: function begin() {
        var info = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  
        if (currentInfo) throw new Error('beginTimer was called before previous endTimer');
        currentInfo = info;
        info.cpuStartTime = now();
        beginQuery(currentInfo);
      },
      end: function end(fn) {
        currentInfo.cpuTime = now() - currentInfo.cpuStartTime;
        delete currentInfo.cpuStartTime;
        currentInfo.callback = fn;
        currentInfo = null;
        endQuery();
  
        if (isPolling === false) {
          isPolling = true;
          requestAnimationFrame(loop);
        }
      }
    };
  }
  
  },{}],26:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.default = TNSL;
  // TNSL (pronounced tinsel)
  // is a domain specific language based on GLSL
  // for helping with the writing code that
  // computes with tensors. 
  
  // A limitation of GLSL is that the condition
  // of any loop has to be statically known 
  // (e.g. counters up to a fixed constant
  // value) which is problematic if we want
  // to write general code that depends on
  // the size of the input tensors
  
  // TNSL adds the following syntax:
  //      #(image.shape)
  // which will be replaced with an ivec4
  // containing the shape of the input tensor "image"
  // automatically
  
  function TNSL(str) {
      if (typeof str != 'string') throw new Error('TNSL shader preprocessor only accepts strings');
  
      return function (uniforms, output) {
          return str
          // comment out the tensor struct definitions
          .replace(/uniform\s*Tensor\s*([\w_]+)\s*;/g, '/* (Tensor $1) */')
  
          // this is the macro syntax
          .replace(/\#\(([\w\.\s]+)\)/g, function (all, body) {
              var obj = uniforms;
              var _iteratorNormalCompletion = true;
              var _didIteratorError = false;
              var _iteratorError = undefined;
  
              try {
                  for (var _iterator = body.split('.')[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                      var part = _step.value;
  
                      obj = obj[part.trim()];
                  }
              } catch (err) {
                  _didIteratorError = true;
                  _iteratorError = err;
              } finally {
                  try {
                      if (!_iteratorNormalCompletion && _iterator.return) {
                          _iterator.return();
                      }
                  } finally {
                      if (_didIteratorError) {
                          throw _iteratorError;
                      }
                  }
              }
  
              if (typeof obj == 'number') {
                  return obj.toString();
              } else if (Array.isArray(obj) && obj.length <= 4 && obj.length > 1) {
                  return (obj.every(Number.isInteger) ? 'i' : '') + 'vec' + obj.length + '(' + obj.join(',') + ')';
              }
              throw new Error('Can not inline expression ' + body);
          })
          // tensor.read4(x, 0) => tensor.read4(ivec4(x, 0, 0, 0))
          // this transformation takes place when there are 2 or more arguments
          // as otherwise it's not possible to statically determine whether x is
          // of type ivec4 or a number
          .replace(/\b(\w+)\s*\.\s*(read4?)\b\s*\(([^\(\)]+)\)/g, function (all, name, prop, arg) {
              if (name in uniforms && uniforms[name].shape) {
                  var parts = arg.split(','),
                      padded = parts.concat(['0', '0', '0', '0'].slice(0, 4 - parts.length));
                  if (parts.length < 2 || parts.length > 4) return all;
                  var vec = 'ivec4(' + padded.join(',') + ')';
                  return name + '_' + prop + '(' + vec + ')';
              }
              return all;
          })
  
          // tensor.shape => tensor_shape
          .replace(/\b(\w+)\s*\.\s*(\w+)\b/g, function (all, name, prop) {
              if (name in uniforms && uniforms[name].shape) {
                  return name + '_' + prop;
              }
              return all;
          });
          // .replace(/\#\s*(\w+)\s*\[(.*?)\]/g, function(all, tensor, body){
          //     return tensor + '_read(ivec4(' + body + '))'
          // })
      };
  }
  
  },{}],27:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  
  var _helpers = require('./helpers.js');
  
  var _index = require('../format/index.js');
  
  var _index2 = _interopRequireDefault(_index);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  // The tensor format is a JSON object that specifies how 
  // the tensor is represented as a texture
  // it consists of several keys:
  
  //     type: uint8 | float32
  //     density: 4:4 | 1:4
  //     pack: stride | tile
  //     codec: 
  //      softfloat | fixnum (1:4)
  //          raw | linquant (4:4)
  
  var BaseTensor = function () {
    function BaseTensor() {
      _classCallCheck(this, BaseTensor);
    }
  
    _createClass(BaseTensor, [{
      key: '_init',
  
      // we arent using a constructor because we want to be able to run
      // this instanceof OutputTensor from within the Tensor constructor
  
      value: function _init(gl, format, shape, data) {
        // validate glcontext
        if (!gl.createTexture) throw new Error('Invalid WebGLRenderingContext');
        this.gl = gl;
  
        // validate shape
        if (!Array.isArray(shape)) throw new Error("shape must be Array");
        if (shape.length > 4) throw new Error("Tensor must have dimension <= 4");
        if (shape.some(function (k) {
          return !isFinite(k) || k < 1 || !Number.isInteger(k);
        })) throw new Error('Invalid shape: ' + shape);
        shape = shape.concat([1, 1, 1, 1]).slice(0, 4);
        this.shape = shape;
  
        // validate format
        if (!['float32', 'uint8'].includes(format.type)) throw new Error('format.type must be uint8 or float32');
        if (format.density in _index2.default) {
          var fd = _index2.default[format.density];
          if (!(format.pack in fd.pack)) throw new Error('format.pack must be ' + Object.keys(fd.pack).join(' or '));
          if (!(format.codec in fd.codec)) throw new Error('format.codec must be ' + Object.keys(fd.codec).join(' or '));
        } else throw new Error('format.density must be ' + Object.keys(_index2.default).join(' or '));
  
        this.format = format;
  
        // calculate texture size
        this.info = Object.assign({}, this._format.pack.init(shape, format), this._format.codec.init(shape, format));
        if (!this.info.texSize) throw new Error('Format did not yield texSize');
  
        // initialize texture
        this.tex = (0, _helpers.makeTexture)(gl);
        this.update(data);
      }
    }, {
      key: '_update',
      value: function _update(data) {
        if (data !== null) {
          if (this.format.type === 'uint8') {
            if (Array.isArray(data) || data instanceof Uint8ClampedArray) data = new Uint8Array(data);
            if (!(data instanceof Uint8Array)) throw new Error('data must be Uint8Array');
          } else if (this.format.type === 'float32') {
            if (Array.isArray(data) || data instanceof Float64Array) data = new Float32Array(data);
            if (!(data instanceof Float32Array)) throw new Error('data must be Float32Array');
          } else throw new Error('Type must be uint8 or float32');
          if (data.length !== this.info.texSize[0] * this.info.texSize[1] * 4) throw new Error('data is the wrong length');
        }
        // if(data) console.log('_update', data);
        var gl = this.gl;
        gl.bindTexture(gl.TEXTURE_2D, this.tex);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.info.texSize[0], this.info.texSize[1], 0, gl.RGBA, this.format.type == 'uint8' ? gl.UNSIGNED_BYTE : gl.FLOAT, data);
      }
    }, {
      key: 'update',
      value: function update(data) {
        if (!data) return this._update(null);
        if (data.shape) return this._update(this._format.pack.pack(this.info, data, this._format.codec.encode, this.format));
        if (this.type != 'uint8') console.warn('Calling update with raw TypedArray may not work across all browsers.');
        return this._update(data);
      }
    }, {
      key: 'destroy',
      value: function destroy() {
        this.gl.deleteTexture(this.tex);
      }
    }, {
      key: '_format',
      get: function get() {
        return {
          pack: _index2.default[this.format.density].pack[this.format.pack],
          codec: _index2.default[this.format.density].codec[this.format.codec],
          activations: _index2.default[this.format.density].activations,
          read_shim: _index2.default[this.format.density].read_shim,
          write_shim: _index2.default[this.format.density].write_shim
        };
      }
    }]);
  
    return BaseTensor;
  }();
  
  exports.default = BaseTensor;
  
  },{"../format/index.js":19,"./helpers.js":29}],28:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.default = runFeatureTests;
  exports.testRenderFloat = testRenderFloat;
  
  var _program = require('../runtime/program.js');
  
  var _helpers = require('./helpers.js');
  
  function runFeatureTests(gl) {
      if (!gl.FLOAT_TEXTURES_TESTED && !gl.NO_FLOAT_TEXTURES) {
          if (!gl.getExtension('OES_texture_float')) {
              console.info("This browser does not seem to support OES_texture_float. " + "Using float codec workaround from now on.");
              gl.NO_FLOAT_TEXTURES = true;
          }
          gl.FLOAT_TEXTURES_TESTED = true;
      }
  
      if (!gl.NO_FLOAT_TEXTURES) {
          if (!gl.RENDER_FLOAT_TESTED && !gl.NO_RENDER_FLOAT) {
              if (!testRenderFloat(gl)) {
                  console.info("This browser supports OES_texture_float, " + "but can not render to floating textures. " + "Using float codec workaround for output tensors from now on.");
                  gl.NO_RENDER_FLOAT = true;
              }
              gl.RENDER_FLOAT_TESTED = true;
          }
  
          if (!gl.READ_FLOAT_TESTED && !gl.NO_READ_FLOAT && !gl.NO_READ_FLOAT) {
              if (!testReadFloat(gl)) {
                  console.info("This browser supports OES_texture_float, " + "can render to floating point textures, but can not " + "read into a Float32Array buffer. Using float codec " + "workaround for reading from output tensors from now on.");
                  gl.NO_READ_FLOAT = true;
              }
              gl.READ_FLOAT_TESTED = true;
          }
      }
  }
  
  var CHECK_FLOAT_VERTEX = '\n    attribute vec2 a_position;\n    void main() {\n        gl_Position = vec4(a_position, 0, 1);\n    }\n';
  var CHECK_FLOAT_FRAGMENT = '\n    void main() {\n        gl_FragColor = vec4(3.14159, -2.71828, 1.61828, 42);\n    }\n';
  
  // some browsers (e.g. mobile safari) are capable of initializing floating 
  // point textures but unable to write to them. The only way of finding this
  // out is by trying to render to a floating point texture and noticing
  // the invalid framebuffer status.
  
  function testRenderFloat(gl) {
      var tex = (0, _helpers.makeTexture)(gl);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 10, 10, 0, gl.RGBA, gl.FLOAT, null);
      var fbo = (0, _helpers.makeFrameBuffer)(gl, tex);
  
      var program = (0, _program.createShaderProgram)(gl, CHECK_FLOAT_VERTEX, CHECK_FLOAT_FRAGMENT);
      gl.useProgram(program);
      (0, _program.bindAttributeBuffer)(gl, program);
  
      gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
      gl.viewport(0, 0, 10, 10);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  
      var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
      gl.deleteTexture(tex);
      gl.deleteFramebuffer(fbo);
      gl.deleteProgram(program);
  
      return status == gl.FRAMEBUFFER_COMPLETE;
  }
  
  function testReadFloat(gl) {
      var tex = (0, _helpers.makeTexture)(gl);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 10, 10, 0, gl.RGBA, gl.FLOAT, null);
      var fbo = (0, _helpers.makeFrameBuffer)(gl, tex);
  
      var program = (0, _program.createShaderProgram)(gl, CHECK_FLOAT_VERTEX, CHECK_FLOAT_FRAGMENT);
      gl.useProgram(program);
      (0, _program.bindAttributeBuffer)(gl, program);
  
      gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
      gl.viewport(0, 0, 10, 10);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  
      var size = [3, 3];
      var pixels = pixels = new Float32Array(size[0] * size[1] * 4);
      gl.readPixels(0, 0, size[0], size[1], gl.RGBA, gl.FLOAT, pixels);
  
      gl.deleteTexture(tex);
      gl.deleteFramebuffer(fbo);
      gl.deleteProgram(program);
  
      var total_error = Math.abs(pixels[0] - 3.14159) + Math.abs(pixels[1] + 2.71828) + Math.abs(pixels[2] - 1.61828) + Math.abs(pixels[3] - 42);
  
      return total_error < 0.01;
  }
  
  },{"../runtime/program.js":24,"./helpers.js":29}],29:[function(require,module,exports){
  "use strict";
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.makeFrameBuffer = makeFrameBuffer;
  exports.makeTexture = makeTexture;
  function makeFrameBuffer(gl, texture) {
      var framebuffer = gl.createFramebuffer();
      gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
      gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
      return framebuffer;
  }
  
  function makeTexture(gl) {
      var texture = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, texture);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  
      return texture;
  }
  
  },{}],30:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.InPlaceTensor = exports.OutputTensor = exports.Tensor = undefined;
  
  var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
  
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  
  var _base = require('./base.js');
  
  var _base2 = _interopRequireDefault(_base);
  
  var _show2 = require('./show.js');
  
  var _show3 = _interopRequireDefault(_show2);
  
  var _feature = require('./feature.js');
  
  var _feature2 = _interopRequireDefault(_feature);
  
  var _helpers = require('./helpers.js');
  
  var _index = require('../runtime/index.js');
  
  var _ndarrayShow = require('ndarray-show');
  
  var _ndarrayShow2 = _interopRequireDefault(_ndarrayShow);
  
  var _ndarray = require('ndarray');
  
  var _ndarray2 = _interopRequireDefault(_ndarray);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  
  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  
  var Tensor = exports.Tensor = function (_BaseTensor) {
      _inherits(Tensor, _BaseTensor);
  
      // new Tensor(gl)
      // new Tensor(gl, [1, 1])
      // new Tensor(gl, [1, 1], null)
      // new Tensor(gl, [1, 1], data)
      // new Tensor(gl, [1, 1], data, { type, pack, codec, density })
      // new Tensor(gl, [1, 1], { type, pack, codec, density })
      // new Tensor(gl, [1, 1], 'softfloat')
      // new Tensor(gl, [1, 1], 'float32')
      // new Tensor(gl, [1, 1], 'uint8')
      // new Tensor(gl, { shape, data })
      // new Tensor(gl, { width, height, data })
      // pix = new Tensor(gl, [1, 1, 4], [1, 0.4, 3, 4], 'uint8')
  
      function Tensor(gl) {
          var shape = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
          var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
          var format = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
  
          _classCallCheck(this, Tensor);
  
          var _this = _possibleConstructorReturn(this, (Tensor.__proto__ || Object.getPrototypeOf(Tensor)).call(this));
  
          (0, _feature2.default)(gl);
  
          var xdata = data;
          if (shape.shape) {
              // ndarrays
              format = data;
              xdata = shape.data;
              data = shape;
              shape = shape.shape;
          }
  
          if (shape.width && shape.height && shape.data) {
              // imagedata
              data = shape.data;
              shape = [shape.width, shape.height];
          }
  
          if (typeof data === 'string') {
              // data = uint8 | float32
              if (format !== null) throw new Error('Format must not be specified if data is a string.');
              format = data;
              data = null;
          } else if (data && (typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object' && data.type && data.codec && data.pack && data.density) {
              if (format !== null) throw new Error('Format must not be specified if data is an object.');
              format = data;
              data = null;
          }
  
          if (format === null) {
              // auto-infer format based on data
              if (data === null) {
                  format = 'float32';
              } else if (xdata instanceof Uint8Array || xdata instanceof Uint8ClampedArray) {
                  format = 'uint8';
              } else if (xdata instanceof Float32Array || xdata instanceof Float64Array || Array.isArray(xdata)) {
                  format = 'float32';
              } else throw new Error("Invalid format for data: must be Uint8Array or Float32Array or ndarray");
          }
  
          var type = null;
          if (format === 'float32' && (gl.NO_FLOAT_TEXTURES || gl.NO_RENDER_FLOAT && _this instanceof OutputTensor) || format === 'softfloat') {
              format = { type: 'uint8', pack: 'stride', density: '1:4', codec: 'softfloat' };
              type = 'float32';
          } else if (format === 'uint8' || format === 'float32') {
              format = { type: format, pack: 'stride', density: '4:4', codec: 'raw' };
          }
  
          _this.type = type || format.type;
          _this._init(gl, format, shape, data);
          return _this;
      }
  
      _createClass(Tensor, [{
          key: 'copy',
          value: function copy() {
              var format = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.type;
              var T = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : OutputTensor;
              var callback = arguments[2];
  
              var TENSOR_IDENTITY = '\n            uniform Tensor image;\n            vec4 process4(ivec4 pos) { return image.read4(pos); }\n        ';
              var out = new T(this.gl, this.shape, format);
              out.run(TENSOR_IDENTITY, { image: this }, callback);
              return out;
          }
      }, {
          key: 'withCopy',
          value: function withCopy(fn) {
              for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
                  args[_key - 1] = arguments[_key];
              }
  
              var copy = this.copy.apply(this, args);
              var result = fn(copy);
              copy.destroy();
              return result;
          }
      }, {
          key: 'ready',
          value: function ready(callback) {
              var _this2 = this;
  
              if (!callback) return new Promise(function (resolve) {
                  return _this2.ready(resolve);
              });
              this.withCopy(function (x) {
                  return x;
              }, this.type, OutputTensor, callback);
          }
      }, {
          key: '_show',
          value: function _show() {
              var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
              (0, _show3.default)(this.gl, this.tex, opt);
          }
      }, {
          key: 'show',
          value: function show() {
              var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  
              var gl = this.gl;
              if (this.format.pack == 'tile' && this.format.density == '4:4' && this.format.codec == 'raw') {
                  this._show(opt);
              } else {
                  // C.info.main_input.output.copy({ type: 'uint8', pack: 'tile', density: '4:4', codec: 'linquant', min: 0, max: 255 })._show({ })
                  this.withCopy(function (x) {
                      return x.show(opt);
                  }, { type: gl.NO_FLOAT_TEXTURES || gl.NO_RENDER_FLOAT ? 'uint8' : 'float32',
                      pack: 'tile', density: '4:4', codec: 'raw' });
              };
          }
      }, {
          key: 'run',
          value: function run(shader, params) {
              throw new Error('Only OutputTensor can run shaders.');
          }
      }, {
          key: 'compile',
          value: function compile(shader, params) {
              throw new Error('Only OutputTensor can compile shaders.');
          }
      }, {
          key: 'read',
          value: function read() {
              console.warn("Copying before read...");
              return this.withCopy(function (x) {
                  return x.read();
              });
          }
      }, {
          key: 'print',
          value: function print() {
              return (0, _ndarrayShow2.default)(this.read());
          }
      }, {
          key: 'swap',
          value: function swap() {
              throw new Error("Only InPlaceTensor can be both a parameter and destination.");
          }
      }]);
  
      return Tensor;
  }(_base2.default);
  
  var OutputTensor = exports.OutputTensor = function (_Tensor) {
      _inherits(OutputTensor, _Tensor);
  
      function OutputTensor() {
          var _ref;
  
          _classCallCheck(this, OutputTensor);
  
          for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
              args[_key2] = arguments[_key2];
          }
  
          var _this3 = _possibleConstructorReturn(this, (_ref = OutputTensor.__proto__ || Object.getPrototypeOf(OutputTensor)).call.apply(_ref, [this].concat(args)));
  
          _this3.fbo = (0, _helpers.makeFrameBuffer)(_this3.gl, _this3.tex);
          return _this3;
      }
  
      _createClass(OutputTensor, [{
          key: 'destroy',
          value: function destroy() {
              _get(OutputTensor.prototype.__proto__ || Object.getPrototypeOf(OutputTensor.prototype), 'destroy', this).call(this);
              this.gl.deleteFramebuffer(this.fbo);
          }
      }, {
          key: '_read',
          value: function _read() {
              var gl = this.gl,
                  size = this.info.texSize;
  
              if (this.format.type == 'uint8') {
                  var glType = gl.UNSIGNED_BYTE,
                      pixels = new Uint8Array(size[0] * size[1] * 4);
              } else if (this.format.type === 'float32') {
                  var glType = gl.FLOAT,
                      pixels = new Float32Array(size[0] * size[1] * 4);
              }
  
              gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);
              gl.readPixels(0, 0, size[0], size[1], gl.RGBA, glType, pixels);
  
              // console.log('___read', pixels)
              return pixels;
          }
      }, {
          key: 'run',
          value: function run(shader, params, callback) {
              return (0, _index.Run)(shader, this, params, callback);
          }
      }, {
          key: 'compile',
          value: function compile(shader, params) {
              return (0, _index.Compile)(shader, this, params);
          }
      }, {
          key: 'read',
          value: function read() {
              if (this.format.type === 'float32' && this.gl.NO_READ_FLOAT) {
                  return this.withCopy(function (x) {
                      return x.read();
                  }, 'softfloat');
              }
  
              var array = this._format.pack.unpack(this.info, this._read(), this._format.codec.decode, this.type);
  
              // strip trailing singleton dimensions
              var shape = array.shape.slice(0),
                  stride = array.stride.slice(0);
              while (shape[shape.length - 1] == 1 && shape.length > 1) {
                  shape.pop();
                  stride.pop();
              }
              return (0, _ndarray2.default)(array.data, shape, stride, array.offset);
          }
      }]);
  
      return OutputTensor;
  }(Tensor);
  
  var InPlaceTensor = exports.InPlaceTensor = function (_OutputTensor) {
      _inherits(InPlaceTensor, _OutputTensor);
  
      function InPlaceTensor() {
          var _ref2;
  
          _classCallCheck(this, InPlaceTensor);
  
          for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
              args[_key3] = arguments[_key3];
          }
  
          var _this4 = _possibleConstructorReturn(this, (_ref2 = InPlaceTensor.__proto__ || Object.getPrototypeOf(InPlaceTensor)).call.apply(_ref2, [this].concat(args)));
  
          _this4.tex2 = _this4.tex;
          _this4.tex = (0, _helpers.makeTexture)(_this4.gl);
          _this4.update(null);
          _this4.swap();
          return _this4;
      }
  
      _createClass(InPlaceTensor, [{
          key: 'destroy',
          value: function destroy() {
              _get(InPlaceTensor.prototype.__proto__ || Object.getPrototypeOf(InPlaceTensor.prototype), 'destroy', this).call(this);
              this.gl.deleteTexture(this.tex2);
          }
      }, {
          key: 'swap',
          value: function swap() {
              var tmp = this.tex;
              this.tex = this.tex2;
              this.tex2 = tmp;
  
              // TODO: investigate performance of using multiple FBOs instead
              // of rebinding the framebuffer
              var gl = this.gl;
              gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);
              gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.tex, 0);
          }
      }]);
  
      return InPlaceTensor;
  }(OutputTensor);
  
  },{"../runtime/index.js":23,"./base.js":27,"./feature.js":28,"./helpers.js":29,"./show.js":31,"ndarray":5,"ndarray-show":4}],31:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.default = showTexture;
  
  var _program = require('../runtime/program.js');
  
  var SHOW_TEXTURE_VERTEX = '\n    attribute vec2 a_position;\n    varying mediump vec2 pos;\n    void main() {\n        pos = (a_position + vec2(1, 1)) / 2.0;\n        gl_Position = vec4(a_position, 0, 1);\n    }\n';
  
  var SHOW_TEXTURE_FRAGMENT = '\n    precision mediump float;\n\n    uniform sampler2D tex;\n    uniform float scale;\n    uniform float offset;\n    uniform bool transpose;\n    uniform bool flipX;\n    uniform bool flipY;\n    uniform int channels;\n\n    varying vec2 pos;\n\n    vec4 colormap(float x) {\n        float r = clamp(8.0 / 3.0 * x, 0.0, 1.0);\n        float g = clamp(8.0 / 3.0 * x - 1.0, 0.0, 1.0);\n        float b = clamp(4.0 * x - 3.0, 0.0, 1.0);\n        return vec4(r, g, b, 1.0);\n    }\n\n    void main() {\n        vec2 p = pos;\n        if(flipX) p.x = 1.0 - p.x;\n        if(flipY) p.y = 1.0 - p.y;\n        if(transpose) p = p.yx;\n        if(channels == 4){\n            gl_FragColor = vec4(vec4(offset, offset, offset, offset) \n                + scale * texture2D(tex, p));\n        }else if(channels == 3){\n            gl_FragColor = vec4(vec3(offset, offset, offset) \n                + scale * texture2D(tex, p).rgb, 1);\n        }else if(channels == 2){\n            gl_FragColor = vec4(vec2(offset, offset) \n                + scale * texture2D(tex, p).rg, 0, 1);\n        }else if(channels == 1){\n            gl_FragColor = colormap(offset + scale * texture2D(tex, p).r);\n        }\n    }\n';
  
  function showTexture(gl, tex) {
      var opt = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  
      if (!gl._showProgram) {
          gl._showProgram = (0, _program.createShaderProgram)(gl, SHOW_TEXTURE_VERTEX, SHOW_TEXTURE_FRAGMENT);
          gl.useProgram(gl._showProgram);
          (0, _program.bindAttributeBuffer)(gl, gl._showProgram);
          gl.uniform1i(gl.getUniformLocation(gl._showProgram, 'tex'), 0);
      }
  
      if (gl.canvas && gl.canvas._tfAuto) {
          gl.canvas.style.display = 'block';
          gl.canvas.style.position = 'absolute';
          gl.canvas.style.top = 0;
          gl.canvas.style.left = 0;
          gl.canvas.style.width = Math.min(innerHeight, innerWidth) + 'px';
          gl.canvas.style.height = Math.min(innerHeight, innerWidth) + 'px';
          gl.canvas.onclick = function () {
              gl.canvas.style.display = 'none';
          };
      }
  
      gl.useProgram(gl._showProgram);
      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, tex);
      gl.uniform1f(gl.getUniformLocation(gl._showProgram, 'scale'), opt.scale || 1);
      gl.uniform1f(gl.getUniformLocation(gl._showProgram, 'offset'), opt.offset || 0);
      gl.uniform1i(gl.getUniformLocation(gl._showProgram, 'transpose'), opt.transpose ? 1 : 0);
      gl.uniform1i(gl.getUniformLocation(gl._showProgram, 'flipX'), opt.flipX ? 1 : 0);
      gl.uniform1i(gl.getUniformLocation(gl._showProgram, 'flipY'), opt.flipY ? 1 : 0);
      gl.uniform1i(gl.getUniformLocation(gl._showProgram, 'channels'), opt.channels || 3);
  
      gl.bindFramebuffer(gl.FRAMEBUFFER, null);
      gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  }
  
  },{"../runtime/program.js":24}],32:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
      value: true
  });
  exports.createGL = createGL;
  function createGL(canvas) {
      if (!canvas) {
          canvas = document.createElement('canvas');
          canvas.width = 512;
          canvas.height = 512;
          canvas.style.display = 'none';
          canvas._tfAuto = true;
          document.body.appendChild(canvas);
      }
      var gl = canvas.getContext("webgl", { antialias: false }) || canvas.getContext("experimental-webgl", { antialias: false });
      if (!gl) alert('Could not initialize WebGL, try another browser');
      return gl;
  }
  
  },{}]},{},[20])(20)
  });