diff --git a/.babelrc.js b/.babelrc.js new file mode 100644 index 0000000000..c488d0ab5a --- /dev/null +++ b/.babelrc.js @@ -0,0 +1,25 @@ +const envOpts = {} + +if (process.env.BABEL_ENV === 'node') { + envOpts.targets = { node: 9 } + envOpts.modules = 'commonjs' +} + +if (process.env.BABEL_ENV === 'browser') { + envOpts.targets = { browsers: ['>0.5%'] } + envOpts.modules = false + envOpts.useBuiltIns = 'entry' +} + +const config = { + comments: false, + presets: [['@babel/env', envOpts]], + plugins: [ + ['babel-plugin-inline-import', { extensions: ['.glsl'] }], + 'lodash', + '@babel/proposal-class-properties', + ['@babel/proposal-object-rest-spread', { useBuiltIns: true }] + ] +} + +module.exports = config diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 940f6bbc54..0000000000 --- a/.eslintrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": ["plugin:vue-libs/recommended"], - "env": { - "mocha": true, - "node": true - } -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..aaadf27d7d --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,21 @@ +module.exports = { + env: { + browser: true, + node: true, + mocha: true, + es6: true + }, + parser: 'babel-eslint', + plugins: ['html'], + rules: { + 'no-console': 0 + }, + globals: { + KerasJS: true, + TEST_DATA: true, + testGlobals: true, + chai: true, + performance: true + }, + extends: 'eslint:recommended' +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..17f03e5ce7 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceRoot}" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..3b66410730 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.ignoreLimitWarning": true +} \ No newline at end of file diff --git a/keras-js/.babelrc.js b/keras-js/.babelrc.js new file mode 100644 index 0000000000..c488d0ab5a --- /dev/null +++ b/keras-js/.babelrc.js @@ -0,0 +1,25 @@ +const envOpts = {} + +if (process.env.BABEL_ENV === 'node') { + envOpts.targets = { node: 9 } + envOpts.modules = 'commonjs' +} + +if (process.env.BABEL_ENV === 'browser') { + envOpts.targets = { browsers: ['>0.5%'] } + envOpts.modules = false + envOpts.useBuiltIns = 'entry' +} + +const config = { + comments: false, + presets: [['@babel/env', envOpts]], + plugins: [ + ['babel-plugin-inline-import', { extensions: ['.glsl'] }], + 'lodash', + '@babel/proposal-class-properties', + ['@babel/proposal-object-rest-spread', { useBuiltIns: true }] + ] +} + +module.exports = config diff --git a/keras-js/.eslintrc.js b/keras-js/.eslintrc.js new file mode 100644 index 0000000000..aaadf27d7d --- /dev/null +++ b/keras-js/.eslintrc.js @@ -0,0 +1,21 @@ +module.exports = { + env: { + browser: true, + node: true, + mocha: true, + es6: true + }, + parser: 'babel-eslint', + plugins: ['html'], + rules: { + 'no-console': 0 + }, + globals: { + KerasJS: true, + TEST_DATA: true, + testGlobals: true, + chai: true, + performance: true + }, + extends: 'eslint:recommended' +} diff --git a/keras-js/README.md b/keras-js/README.md new file mode 100644 index 0000000000..be553c6077 --- /dev/null +++ b/keras-js/README.md @@ -0,0 +1,286 @@ +# vue-cli [![Build Status](https://img.shields.io/circleci/project/vuejs/vue-cli/master.svg)](https://circleci.com/gh/vuejs/vue-cli) [![npm package](https://img.shields.io/npm/v/vue-cli.svg)](https://www.npmjs.com/package/vue-cli) + +A simple CLI for scaffolding Vue.js projects. + +### Installation + +Prerequisites: [Node.js](https://nodejs.org/en/) (>=4.x, 6.x preferred), npm version 3+ and [Git](https://git-scm.com/). + +``` bash +$ npm install -g vue-cli +``` + +### Usage + +``` bash +$ vue init +``` + +Example: + +``` bash +$ vue init webpack my-project +``` + +The above command pulls the template from [vuejs-templates/webpack](https://github.com/vuejs-templates/webpack), prompts for some information, and generates the project at `./my-project/`. + +### vue build + +Use vue-cli as a zero-configuration development tool for your Vue apps and component, check out the [docs](/docs/build.md). + +### Official Templates + +The purpose of official Vue project templates are to provide opinionated, battery-included development tooling setups so that users can get started with actual app code as fast as possible. However, these templates are un-opinionated in terms of how you structure your app code and what libraries you use in addition to Vue.js. + +All official project templates are repos in the [vuejs-templates organization](https://github.com/vuejs-templates). When a new template is added to the organization, you will be able to run `vue init ` to use that template. You can also run `vue list` to see all available official templates. + +Current available templates include: + +- [webpack](https://github.com/vuejs-templates/webpack) - A full-featured Webpack + vue-loader setup with hot reload, linting, testing & css extraction. + +- [webpack-simple](https://github.com/vuejs-templates/webpack-simple) - A simple Webpack + vue-loader setup for quick prototyping. + +- [browserify](https://github.com/vuejs-templates/browserify) - A full-featured Browserify + vueify setup with hot-reload, linting & unit testing. + +- [browserify-simple](https://github.com/vuejs-templates/browserify-simple) - A simple Browserify + vueify setup for quick prototyping. + +- [pwa](https://github.com/vuejs-templates/pwa) - PWA template for vue-cli based on the webpack template + +- [simple](https://github.com/vuejs-templates/simple) - The simplest possible Vue setup in a single HTML file + +### Custom Templates + +It's unlikely to make everyone happy with the official templates. You can simply fork an official template and then use it via `vue-cli` with: + +``` bash +vue init username/repo my-project +``` + +Where `username/repo` is the GitHub repo shorthand for your fork. + +The shorthand repo notation is passed to [download-git-repo](https://github.com/flipxfx/download-git-repo) so you can also use things like `bitbucket:username/repo` for a Bitbucket repo and `username/repo#branch` for tags or branches. + +If you would like to download from a private repository use the `--clone` flag and the cli will use `git clone` so your SSH keys are used. + +### Local Templates + +Instead of a GitHub repo, you can also use a template on your local file system: + +``` bash +vue init ~/fs/path/to-custom-template my-project +``` + +### Writing Custom Templates from Scratch + +- A template repo **must** have a `template` directory that holds the template files. + +- A template repo **may** have a metadata file for the template which can be either a `meta.js` or `meta.json` file. It can contain the following fields: + + - `prompts`: used to collect user options data; + + - `filters`: used to conditional filter files to render. + + - `metalsmith`: used to add custom metalsmith plugins in the chain. + + - `completeMessage`: the message to be displayed to the user when the template has been generated. You can include custom instruction here. + + - `complete`: Instead of using `completeMessage`, you can use a function to run stuffs when the template has been generated. + +#### prompts + +The `prompts` field in the metadata file should be an object hash containing prompts for the user. For each entry, the key is the variable name and the value is an [Inquirer.js question object](https://github.com/SBoudrias/Inquirer.js/#question). Example: + +``` json +{ + "prompts": { + "name": { + "type": "string", + "required": true, + "message": "Project name" + } + } +} +``` + +After all prompts are finished, all files inside `template` will be rendered using [Handlebars](http://handlebarsjs.com/), with the prompt results as the data. + +##### Conditional Prompts + +A prompt can be made conditional by adding a `when` field, which should be a JavaScript expression evaluated with data collected from previous prompts. For example: + +``` json +{ + "prompts": { + "lint": { + "type": "confirm", + "message": "Use a linter?" + }, + "lintConfig": { + "when": "lint", + "type": "list", + "message": "Pick a lint config", + "choices": [ + "standard", + "airbnb", + "none" + ] + } + } +} +``` + +The prompt for `lintConfig` will only be triggered when the user answered yes to the `lint` prompt. + +##### Pre-registered Handlebars Helpers + +Two commonly used Handlebars helpers, `if_eq` and `unless_eq` are pre-registered: + +``` handlebars +{{#if_eq lintConfig "airbnb"}};{{/if_eq}} +``` + +##### Custom Handlebars Helpers + +You may want to register additional Handlebars helpers using the `helpers` property in the metadata file. The object key is the helper name: + +``` js +module.exports = { + helpers: { + lowercase: str => str.toLowerCase() + } +} +``` + +Upon registration, they can be used as follows: + +``` handlebars +{{ lowercase name }} +``` + +#### File filters + +The `filters` field in the metadata file should be an object hash containing file filtering rules. For each entry, the key is a [minimatch glob pattern](https://github.com/isaacs/minimatch) and the value is a JavaScript expression evaluated in the context of prompt answers data. Example: + +``` json +{ + "filters": { + "test/**/*": "needTests" + } +} +``` + +Files under `test` will only be generated if the user answered yes to the prompt for `needTests`. + +Note that the `dot` option for minimatch is set to `true` so glob patterns would also match dotfiles by default. + +#### Skip rendering + +The `skipInterpolation` field in the metadata file should be a [minimatch glob pattern](https://github.com/isaacs/minimatch). The files matched should skip rendering. Example: + +``` json +{ + "skipInterpolation": "src/**/*.vue" +} +``` + +#### Metalsmith + +`vue-cli` uses [metalsmith](https://github.com/segmentio/metalsmith) to generate the project. + +You may customize the metalsmith builder created by vue-cli to register custom plugins. + +```js +{ + "metalsmith": function (metalsmith, opts, helpers) { + function customMetalsmithPlugin (files, metalsmith, done) { + // Implement something really custom here. + done(null, files) + } + + metalsmith.use(customMetalsmithPlugin) + } +} +``` + +If you need to hook metalsmith before questions are asked, you may use an object with `before` key. + +```js +{ + "metalsmith": { + before: function (metalsmith, opts, helpers) {}, + after: function (metalsmith, opts, helpers) {} + } +} +``` + +#### Additional data available in meta.{js,json} + +- `destDirName` - destination directory name + +```json +{ + "completeMessage": "To get started:\n\n cd {{destDirName}}\n npm install\n npm run dev" +} +``` + +- `inPlace` - generating template into current directory + +```json +{ + "completeMessage": "{{#inPlace}}To get started:\n\n npm install\n npm run dev.{{else}}To get started:\n\n cd {{destDirName}}\n npm install\n npm run dev.{{/inPlace}}" +} +``` + +### `complete` function + +Arguments: + +- `data`: the same data you can access in `completeMessage`: + ```js + { + complete (data) { + if (!data.inPlace) { + console.log(`cd ${data.destDirName}`) + } + } + } + ``` + +- `helpers`: some helpers you can use to log results. + - `chalk`: the `chalk` module + - `logger`: [the built-in vue-cli logger](/lib/logger.js) + - `files`: An array of generated files + ```js + { + complete (data, {logger, chalk}) { + if (!data.inPlace) { + logger.log(`cd ${chalk.yellow(data.destDirName)}`) + } + } + } + ``` + +### Installing a specific template version + +`vue-cli` uses the tool [`download-git-repo`](https://github.com/flipxfx/download-git-repo) to download the official templates used. The `download-git-repo` tool allows you to indicate a specific branch for a given repository by providing the desired branch name after a pound sign (`#`). + +The format needed for a specific official template is: + +``` +vue init '#' +``` + +Example: + +Installing the [`1.0` branch](https://github.com/vuejs-templates/webpack-simple/tree/1.0) of the webpack-simple vue template: + +``` +vue init 'webpack-simple#1.0' mynewproject +``` + +_Note_: The surrounding quotes are necessary on zsh shells because of the special meaning of the `#` character. + + +### License + +[MIT](http://opensource.org/licenses/MIT) diff --git a/keras-js/appveyor.yml b/keras-js/appveyor.yml new file mode 100644 index 0000000000..cd3f817e93 --- /dev/null +++ b/keras-js/appveyor.yml @@ -0,0 +1,18 @@ +environment: + matrix: + - nodejs_version: "6" + - nodejs_version: "8" + +install: + - ps: Install-Product node $env:nodejs_version + - npm install + +test_script: + - node --version + - npm --version + - npm test + +cache: + - node_modules -> package-lock.json + +build: off diff --git a/keras-js/circle.yml b/keras-js/circle.yml new file mode 100644 index 0000000000..b00026e213 --- /dev/null +++ b/keras-js/circle.yml @@ -0,0 +1,3 @@ +machine: + node: + version: 6 diff --git a/keras-js/lib/Layer.js b/keras-js/lib/Layer.js new file mode 100644 index 0000000000..e218b0e2b3 --- /dev/null +++ b/keras-js/lib/Layer.js @@ -0,0 +1,55 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _WebGL = require("./WebGL2"); + +class Layer { + constructor(attrs = {}) { + this.layerClass = 'Layer'; + this.name = attrs.name; + this.gpu = _WebGL.webgl2.isSupported && attrs.gpu; + this.params = []; + this.weights = {}; + this.inbound = []; + this.outbound = []; + } + + throwError(message) { + throw new Error(`[${this.layerClass} layer: ${this.name || ''}] ${message}`); + } + + toggleGPU(mode) { + const newMode = typeof mode === 'undefined' ? !this.gpu : mode; + + if (_WebGL.webgl2.isSupported && newMode) { + this.gpu = true; + } else { + this.gpu = false; + } + } + + setWeights(weightsArr, createGLTexture = true) { + this.params.forEach((p, i) => { + this.weights[p] = weightsArr[i]; + + if (this.gpu && createGLTexture) { + this.weights[p].createGLTexture({ + type: '2d', + format: 'float' + }); + } + }); + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = Layer; \ No newline at end of file diff --git a/keras-js/lib/Model.js b/keras-js/lib/Model.js new file mode 100644 index 0000000000..584f591920 --- /dev/null +++ b/keras-js/lib/Model.js @@ -0,0 +1,493 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _keys2 = _interopRequireDefault(require("lodash/keys")); + +var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); + +var _map2 = _interopRequireDefault(require("lodash/map")); + +var _every2 = _interopRequireDefault(require("lodash/every")); + +var _find2 = _interopRequireDefault(require("lodash/find")); + +var _bluebird = _interopRequireDefault(require("bluebird")); + +var _axios = _interopRequireDefault(require("axios")); + +var _performanceNow = _interopRequireDefault(require("performance-now")); + +var layers = _interopRequireWildcard(require("./layers")); + +var visMethods = _interopRequireWildcard(require("./visualizations")); + +var _Tensor = _interopRequireDefault(require("./Tensor")); + +var _WebGL = require("./WebGL2"); + +var _proto = _interopRequireDefault(require("./proto")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const axiosSource = _axios.default.CancelToken.source(); + +class Model { + constructor(config = {}) { + const { + filepath = null, + headers = {}, + filesystem = false, + gpu = false, + transferLayerOutputs = false, + pauseAfterLayerCalls = false, + visualizations = [] + } = config; + + if (!filepath) { + throw new Error('[Model] path to protobuf-serialized model definition file is missing.'); + } + + this.filepath = filepath; + this.headers = headers; + this.filesystem = typeof window !== 'undefined' ? false : filesystem; + this.dataRequestProgress = 0; + this.id = null; + this.name = null; + this.kerasVersion = null; + this.backend = null; + this.modelConfig = {}; + this.modelWeights = []; + this.gpu = typeof window !== 'undefined' && _WebGL.webgl2.isSupported ? gpu : false; + this.transferLayerOutputs = transferLayerOutputs; + this.pauseAfterLayerCalls = pauseAfterLayerCalls; + this.modelLayersMap = new Map(); + this.inputTensorsMap = new Map(); + this.inputLayerNames = []; + this.outputLayerNames = []; + this.finishedLayerNames = []; + this.isRunning = false; + this.predictStats = {}; + this.visMap = new Map(); + visualizations.forEach(v => { + if (v in visMethods) { + const visInstance = new visMethods[v]({ + modelLayersMap: this.modelLayersMap, + gpu: this.gpu + }); + this.visMap.set(v, visInstance); + } + }); + this._ready = this._initialize(); + } + + checkGPUSupport() { + return _WebGL.webgl2.isSupported; + } + + ready() { + return this._ready; + } + + _interrupt() { + axiosSource.cancel(); + } + + async _initialize() { + try { + const req = this.filesystem ? this._dataRequestFS() : this._dataRequestHTTP(this.headers); + await req; + } catch (err) { + console.log(err); + + this._interrupt(); + } + + this._buildDAG(); + + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name); + inputLayer.call(this.inputTensorsMap.get(name)); + inputLayer.hasOutput = true; + inputLayer.visited = true; + }); + await this._traverseDAG(this.inputLayerNames); + this.finishedLayerNames = []; + this.modelLayersMap.forEach(layer => { + layer.hasOutput = false; + layer.visited = false; + }); + this.visMap.forEach(visInstance => { + visInstance.initialize(); + }); + return true; + } + + async _dataRequestHTTP(headers = {}) { + try { + const res = await _axios.default.get(this.filepath, { + responseType: 'arraybuffer', + headers, + onDownloadProgress: e => { + if (e.lengthComputable) { + const percentComplete = Math.round(100 * e.loaded / e.total); + this.dataRequestProgress = percentComplete; + } + }, + cancelToken: axiosSource.token + }); + this.decodeProtobuf(new Uint8Array(res.data)); + } catch (err) { + if (_axios.default.isCancel(err)) { + console.log('[Model] Data request canceled', err.message); + } else { + throw err; + } + } + + this.dataRequestProgress = 100; + } + + async _dataRequestFS() { + const readFile = _bluebird.default.promisify(require('fs').readFile); + + try { + const file = await readFile(this.filepath); + this.decodeProtobuf(file); + } catch (err) { + throw err; + } + + this.dataRequestProgress = 100; + } + + decodeProtobuf(buffer) { + const err = _proto.default.Model.verify(buffer); + + if (err) { + throw new Error(`[Model] Invalid model - check protobuf serialization: {err}`); + } + + const model = _proto.default.Model.decode(buffer); + + this.id = model.id; + this.name = model.name; + this.kerasVersion = model.kerasVersion; + this.backend = model.backend; + this.modelConfig = JSON.parse(model.modelConfig); + this.modelWeights = model.modelWeights; + } + + getLoadingProgress() { + return this.dataRequestProgress; + } + + toggleGPU(mode) { + if (typeof mode === 'undefined') { + this.gpu = !this.gpu; + } else { + this.gpu = mode; + } + + this.modelLayersMap.forEach(layer => { + layer.toggleGPU(this.gpu); + }); + this.visMap.forEach(visInstance => { + visInstance.gpu = this.gpu; + }); + this.resetInputTensors(); + } + + resetInputTensors() { + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name); + this.inputTensorsMap.set(name, new _Tensor.default([], inputLayer.shape)); + }); + } + + _buildDAG() { + const modelClass = this.modelConfig.class_name; + let modelConfig = []; + + if (modelClass === 'Sequential') { + modelConfig = this.modelConfig.config; + } else if (modelClass === 'Model') { + modelConfig = this.modelConfig.config.layers; + } + + if (!(Array.isArray(modelConfig) && modelConfig.length)) { + throw new Error('[Model] Model configuration does not contain any layers.'); + } + + modelConfig.forEach((layerDef, index) => { + const layerClass = layerDef.class_name; + const layerConfig = layerDef.config; + + if (modelClass === 'Model' && layerClass === 'Sequential') { + layerConfig.forEach((branchLayerDef, branchIndex) => { + const branchLayerClass = branchLayerDef.class_name; + const branchLayerConfig = branchLayerDef.config; + const branchInboundLayerNames = branchIndex === 0 ? layerDef.inbound_nodes[0].map(node => node[0]) : [layerConfig[branchIndex - 1].config.name]; + + this._createLayer(branchLayerClass, branchLayerConfig, branchInboundLayerNames); + }); + } else if (!(layerClass in layers)) { + throw new Error(`[Model] Layer ${layerClass} specified in model configuration is not implemented!`); + } else { + if (modelClass === 'Sequential' && index === 0) { + const inputName = 'input'; + const inputShape = layerConfig.batch_input_shape.slice(1); + const layer = new layers.InputLayer({ + name: inputName, + shape: inputShape, + gpu: this.gpu + }); + this.modelLayersMap.set(inputName, layer); + this.inputTensorsMap.set(inputName, new _Tensor.default([], inputShape)); + this.inputLayerNames.push(inputName); + } else if (modelClass === 'Model' && layerClass === 'InputLayer') { + const inputShape = layerConfig.batch_input_shape.slice(1); + this.inputTensorsMap.set(layerConfig.name, new _Tensor.default([], inputShape)); + this.inputLayerNames.push(layerConfig.name); + } + + let inboundLayerNames = []; + + if (modelClass === 'Sequential') { + if (index === 0) { + inboundLayerNames = ['input']; + } else { + inboundLayerNames = [modelConfig[index - 1].config.name]; + } + } else if (modelClass === 'Model') { + const inboundNodes = layerDef.inbound_nodes; + + if (inboundNodes && inboundNodes.length) { + inboundLayerNames = inboundNodes[0].map(node => node[0]); + } + } + + this._createLayer(layerClass, layerConfig, inboundLayerNames); + } + }); + this.modelLayersMap.forEach(layer => { + if (layer.outbound.length === 0) { + this.outputLayerNames.push(layer.name); + } + }); + this.inputLayerNames.sort(); + this.outputLayerNames.sort(); + } + + _createLayer(layerClass, layerConfig, inboundLayerNames) { + const layer = new layers[layerClass](Object.assign({}, layerConfig, { + gpu: this.gpu + })); + let weightNames = []; + + if (layerClass === 'Bidirectional') { + const forwardWeightNames = layer.forwardLayer.params.map(param => `${layerConfig.name}/forward_${layerConfig.layer.config.name}/${param}`); + const backwardWeightNames = layer.backwardLayer.params.map(param => `${layerConfig.name}/backward_${layerConfig.layer.config.name}/${param}`); + weightNames = forwardWeightNames.concat(backwardWeightNames); + } else if (layerClass === 'TimeDistributed') { + weightNames = layer.layer.params.map(param => `${layerConfig.name}/${param}`); + } else { + weightNames = layer.params.map(param => `${layerConfig.name}/${param}`); + } + + if (weightNames && weightNames.length) { + const weights = weightNames.map(weightName => { + const weightDef = (0, _find2.default)(this.modelWeights, w => { + const weightRE = new RegExp(`^${weightName}`); + return weightRE.test(w.weightName); + }); + + if (!weightDef) { + throw new Error(`[Model] error loading weights.`); + } + + const { + data, + shape, + type + } = weightDef; + const buf = new ArrayBuffer(data.byteLength); + const arr = new Uint8Array(buf); + arr.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); + + if (type === 'uint8') { + const { + quantizeMin, + quantizeMax + } = weightDef; + const unquantized = new Float32Array(arr); + + for (let i = 0, len = unquantized.length; i < len; i++) { + unquantized[i] *= (quantizeMax - quantizeMin) / 255; + unquantized[i] += quantizeMin; + } + + return new _Tensor.default(unquantized, shape); + } else { + return new _Tensor.default(new Float32Array(buf), shape); + } + }); + layer.setWeights(weights); + } + + this.modelLayersMap.set(layerConfig.name, layer); + inboundLayerNames.forEach(layerName => { + this.modelLayersMap.get(layerConfig.name).inbound.push(layerName); + this.modelLayersMap.get(layerName).outbound.push(layerConfig.name); + }); + } + + async _traverseDAG(nodes) { + if (nodes.length === 0) { + return true; + } else if (nodes.length === 1) { + const node = nodes[0]; + const currentLayer = this.modelLayersMap.get(node); + + if (currentLayer.layerClass === 'InputLayer') { + this.finishedLayerNames.push(this.modelLayersMap.get(node).name); + } else { + const currentLayer = this.modelLayersMap.get(node); + + if (currentLayer.visited) { + return false; + } + + const inboundLayers = currentLayer.inbound.map(n => this.modelLayersMap.get(n)); + + if (!(0, _every2.default)((0, _map2.default)(inboundLayers, 'hasOutput'))) { + return false; + } + + if (currentLayer.isMergeLayer) { + currentLayer.call((0, _map2.default)(inboundLayers, 'output')); + } else { + currentLayer.call(inboundLayers[0].output); + } + + currentLayer.hasOutput = true; + currentLayer.visited = true; + this.finishedLayerNames.push(currentLayer.name); + + if (this.pauseAfterLayerCalls) { + await _bluebird.default.delay(0); + } + } + + await this._traverseDAG(currentLayer.outbound); + } else { + await _bluebird.default.all(nodes.map(node => this._traverseDAG([node]))); + } + } + + _maybeTransferIntermediateOutputs() { + if (this.gpu && this.transferLayerOutputs) { + this.modelLayersMap.forEach(layer => { + if (layer.output && layer.output.glTexture) { + _WebGL.webgl2.bindOutputTexture(layer.output.glTexture, layer.output.glTextureShape); + + layer.output.transferFromGLTexture(); + + if (layer.output.is2DReshaped) { + layer.output.reshapeFrom2D(); + } + } + }); + } + } + + loadData(inputData) { + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name); + this.inputTensorsMap.get(name).replaceTensorData(inputData[name]); + inputLayer.call(this.inputTensorsMap.get(name)); + inputLayer.hasOutput = true; + inputLayer.visited = true; + }); + } + + async predict(inputData) { + this.isRunning = true; + + if (!(0, _isEqual2.default)((0, _keys2.default)(inputData).sort(), this.inputLayerNames)) { + this.isRunning = false; + throw new Error('[Model] predict() must take an object where the keys are the named inputs of the model: ' + JSON.stringify(this.inputLayerNames)); + } + + if (!(0, _every2.default)(this.inputLayerNames, name => inputData[name] instanceof Float32Array)) { + this.isRunning = false; + throw new Error('[Model] predict() must take an object where the values are the flattened data as Float32Array.'); + } + + this.finishedLayerNames = []; + this.modelLayersMap.forEach(layer => { + layer.hasOutput = false; + layer.visited = false; + }); + let start = (0, _performanceNow.default)(); + this.loadData(inputData); + this.predictStats.loadData = (0, _performanceNow.default)() - start; + start = (0, _performanceNow.default)(); + await this._traverseDAG(this.inputLayerNames); + this.predictStats.forwardPass = (0, _performanceNow.default)() - start; + + this._maybeTransferIntermediateOutputs(); + + const modelClass = this.modelConfig.class_name; + const outputData = {}; + + if (modelClass === 'Sequential') { + const outputLayer = this.modelLayersMap.get(this.outputLayerNames[0]); + outputData['output'] = outputLayer.output.tensor.data; + } else if (modelClass === 'Model') { + this.outputLayerNames.forEach(layerName => { + const outputLayer = this.modelLayersMap.get(layerName); + outputData[layerName] = outputLayer.output.tensor.data; + }); + } + + start = (0, _performanceNow.default)(); + this.visMap.forEach(visInstance => { + visInstance.update(); + }); + this.predictStats.visualizations = (0, _performanceNow.default)() - start; + this.isRunning = false; + return outputData; + } + + layerCall(layerName, input) { + if (!this.modelLayersMap.has(layerName)) return; + let x; + + if (input instanceof _Tensor.default) { + x = input; + } else { + x = new _Tensor.default(input.data, input.shape); + } + + const layer = this.modelLayersMap.get(layerName); + return layer.call(x); + } + + cleanup() { + _WebGL.webgl2.clearRefs(); + + this.modelLayersMap.clear(); + this.inputTensorsMap.clear(); + this.visMap.clear(); + delete this.modelWeights; + } + +} + +exports.default = Model; \ No newline at end of file diff --git a/keras-js/lib/Tensor.js b/keras-js/lib/Tensor.js new file mode 100644 index 0000000000..b63dc12163 --- /dev/null +++ b/keras-js/lib/Tensor.js @@ -0,0 +1,386 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _WebGL = require("./WebGL2"); + +var tensorUtils = _interopRequireWildcard(require("./utils/tensorUtils")); + +var _ndarray = _interopRequireDefault(require("ndarray")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarraySqueeze = _interopRequireDefault(require("ndarray-squeeze")); + +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; } } + +class Tensor { + constructor(data, shape, options = {}) { + this.arrayType = options.type || Float32Array; + + if (data && data.length && (data instanceof this.arrayType || data instanceof Array)) { + tensorUtils.checkShape(data, shape); + + if (data instanceof this.arrayType) { + this.tensor = (0, _ndarray.default)(data, shape); + } else if (data instanceof Array) { + this.tensor = (0, _ndarray.default)(new this.arrayType(data), shape); + } + } else if (!data.length && shape.length) { + this.tensor = (0, _ndarray.default)(new this.arrayType(shape.reduce((a, b) => a * b, 1)), shape); + } else { + this.tensor = (0, _ndarray.default)(new this.arrayType([]), []); + } + } + + createGLTexture({ + type = '2d', + format = 'float', + supportsTextureFragments = false + }) { + let shape = []; + + if (this.tensor.shape.length === 1) { + shape = [1, this.tensor.shape[0]]; + this.is1D = true; + } else if (this.tensor.shape.length === 2) { + shape = this.tensor.shape; + } else if (this.tensor.shape.length === 3 && (type === '2d_array' || type === '3d')) { + shape = this.tensor.shape; + } else { + throw new Error('[Tensor] cannot create WebGL2 texture.'); + } + + this.glTextureShape = shape; + this.glTextureType = type; + this.glTextureFormat = format; + + if (type === '2d') { + if (this.glTextureShape[0] > _WebGL.MAX_TEXTURE_SIZE && supportsTextureFragments) { + this._create2DRowFragmentedGLTexture(); + } else { + this._create2DGLTexture(); + } + } else if (type === '2d_array' || type === '3d') { + this._create3DGLTexture(); + } else { + throw new Error(`[Tensor] invalid type ${type}.`); + } + } + + _create2DGLTexture() { + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + } = textureOptions; + this.glTexture = gl.createTexture(); + + _WebGL.webgl2.storeRef('texture', this.glTexture); + + gl.bindTexture(textureTarget, this.glTexture); + const shape = this.glTextureShape; + const data = this.tensor.data; + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } + + _create2DRowFragmentedGLTexture() { + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + } = textureOptions; + this.glTextureFragments = []; + this.glTextureFragmentShape = [_WebGL.MAX_TEXTURE_SIZE, this.glTextureShape[1]]; + const shape = this.glTextureFragmentShape; + const numFragments = Math.ceil(this.glTextureShape[0] / _WebGL.MAX_TEXTURE_SIZE); + let offset = 0; + + for (let k = 0; k < numFragments; k++) { + const glTexture = gl.createTexture(); + + _WebGL.webgl2.storeRef('texture', glTexture); + + gl.bindTexture(textureTarget, glTexture); + let data; + + if (k === numFragments - 1) { + data = new this.arrayType(shape[0] * shape[1]); + data.set(this.tensor.data.slice(offset, offset + shape[0] * shape[1]), 0); + } else { + data = this.tensor.data.slice(offset, offset + shape[0] * shape[1]); + } + + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + this.glTextureFragments.push(glTexture); + offset += shape[0] * shape[1]; + } + } + + _create3DGLTexture() { + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + } = textureOptions; + this.glTexture = gl.createTexture(); + + _WebGL.webgl2.storeRef('texture', this.glTexture); + + gl.bindTexture(textureTarget, this.glTexture); + const shape = this.glTextureShape; + const data = tensorUtils.data3DLayoutForGL(this.arrayType, this.tensor, this.glTextureShape); + gl.texImage3D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], shape[2], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } + + convert2DRowFragmentedGLTextureToColStack() { + if (!this.glTextureFragments || !this.glTextureFragmentShape) { + throw new Error('[Tensor] no glTextureFragments available.'); + } + + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + } = textureOptions; + + if (!this.glTextureFragmentsAsColStack) { + this.glTextureFragmentsAsColStack = gl.createTexture(); + + _WebGL.webgl2.storeRef('texture', this.glTextureFragmentsAsColStack); + + gl.bindTexture(textureTarget, this.glTextureFragmentsAsColStack); + const numFragments = this.glTextureFragments.length; + this.glTextureFragmentsAsColStackShape = [this.glTextureFragmentShape[0], this.glTextureFragmentShape[1] * numFragments]; + const shape = this.glTextureFragmentsAsColStackShape; + const data = new this.arrayType(shape.reduce((a, b) => a * b, 1)); + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } else { + gl.bindTexture(textureTarget, this.glTextureFragmentsAsColStack); + } + + const fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo); + this.glTextureFragments.forEach((texture, k) => { + gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + gl.copyTexSubImage2D(textureTarget, 0, k * this.glTextureFragmentShape[1], 0, 0, 0, this.glTextureFragmentShape[1], this.glTextureFragmentShape[0]); + }); + gl.deleteFramebuffer(fbo); + } + + removeGLTextureFragmentsAsColStack() { + if (this.glTextureFragmentsAsColStack) { + const gl = _WebGL.webgl2.context; + gl.deleteTexture(this.glTextureFragmentsAsColStack); + delete this.glTextureFragmentsAsColStack; + delete this.glTextureFragmentsAsColStackShape; + } + } + + deleteGLTexture() { + const gl = _WebGL.webgl2.context; + + if (this.glTexture) { + gl.deleteTexture(this.glTexture); + delete this.glTexture; + } + + if (this.glTextureFragments) { + this.glTextureFragments.forEach(texture => { + gl.deleteTexture(texture); + }); + delete this.glTextureFragments; + } + } + + replaceTensorData(data) { + if (data && data.length && data instanceof this.arrayType) { + this.tensor.data.set(data); + } else if (data && data.length && data instanceof Array) { + this.tensor.data.set(new this.arrayType(data)); + } else { + throw new Error('[Tensor] invalid input for replaceTensorData method.'); + } + + if (this.glTexture) { + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureFormat, + textureType + } = textureOptions; + gl.bindTexture(textureTarget, this.glTexture); + const shape = this.glTextureShape; + + if (this.glTextureType === '2d') { + const data = this.tensor.data; + gl.texSubImage2D(textureTarget, 0, 0, 0, shape[1], shape[0], textureFormat, textureType, data, 0); + } else if (this.glTextureType === '2d_array' || this.glTextureType === '3d') { + const data = tensorUtils.data3DLayoutForGL(this.arrayType, this.tensor, shape); + gl.texSubImage3D(textureTarget, 0, 0, 0, 0, shape[1], shape[0], shape[2], textureFormat, textureType, data, 0); + } + } + } + + transferFromGLTexture() { + if (this.glTextureFragments) { + this.tensor = (0, _ndarray.default)(new this.arrayType(this.glTextureShape[0] * this.glTextureShape[1]), this.glTextureShape); + let offset = 0; + + for (let k = 0; k < this.glTextureFragments.length; k++) { + _WebGL.webgl2.bindOutputTexture(this.glTextureFragments[k], this.glTextureFragmentShape); + + const fragmentData = _WebGL.webgl2.readData(this.glTextureFragmentShape); + + if (k === this.glTextureFragments.length - 1) { + const truncate = this.tensor.data.length - offset; + this.tensor.data.set(fragmentData.subarray(0, truncate), offset); + } else { + this.tensor.data.set(fragmentData, offset); + } + + offset += fragmentData.length; + } + } else { + _WebGL.webgl2.bindOutputTexture(this.glTexture, this.glTextureShape); + + this.tensor = (0, _ndarray.default)(new this.arrayType([]), this.glTextureShape); + this.tensor.data = _WebGL.webgl2.readData(this.glTextureShape); + } + + if (this.is1D && this.glTextureShape[0] === 1) { + this.tensor = (0, _ndarraySqueeze.default)(this.tensor, [0]); + } + } + + reshapeTo2D() { + const axis = this.tensor.shape.length - 1; + const axisSize = this.tensor.shape[axis]; + const otherAxes = this.tensor.shape.slice(0, axis); + const otherAxesSize = otherAxes.reduce((a, b) => a * b, 1); + const reshaped = (0, _ndarray.default)(new this.arrayType(otherAxesSize * axisSize), [otherAxesSize, axisSize]); + const otherAxesData = (0, _ndarray.default)(new this.arrayType(otherAxesSize), otherAxes); + const otherAxesDataRaveled = (0, _ndarray.default)(new this.arrayType(otherAxesSize), [otherAxesSize]); + const axisSlices = Array(this.tensor.shape.length).fill(null); + + for (let n = 0; n < axisSize; n++) { + axisSlices[axis] = n; + + _ndarrayOps.default.assign(otherAxesData, this.tensor.pick(...axisSlices)); + + otherAxesDataRaveled.data = otherAxesData.data; + + _ndarrayOps.default.assign(reshaped.pick(null, n), otherAxesDataRaveled); + } + + this.originalShape = this.tensor.shape; + this.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.tensor.shape, false, axis); + this.tensor = reshaped; + this.is2DReshaped = true; + } + + reshapeFrom2D(axis = -1) { + if (!this.is2DReshaped) { + throw new Error('[Tensor] not in reshaped 2D representation.'); + } + + if (!this.originalShape) { + throw new Error('[Tensor] does not contain originalShape.'); + } + + if (axis < 0) { + axis = this.originalShape.length + axis; + } + + const channelDataSize = this.tensor.shape[0]; + const channels = this.tensor.shape[1]; + const reshaped = (0, _ndarray.default)(new this.arrayType(this.originalShape.reduce((a, b) => a * b, 1)), this.originalShape); + const channelDataRaveled = (0, _ndarray.default)(new this.arrayType(channelDataSize), [channelDataSize]); + const unraveledChannelShape = [...this.originalShape.slice(0, axis), ...this.originalShape.slice(axis + 1)]; + const unraveledChannel = (0, _ndarray.default)(new this.arrayType(unraveledChannelShape.reduce((a, b) => a * b, 1)), unraveledChannelShape); + const axisSlices = Array(this.originalShape.length).fill(null); + + for (let n = 0; n < channels; n++) { + _ndarrayOps.default.assign(channelDataRaveled, this.tensor.pick(null, n)); + + unraveledChannel.data = channelDataRaveled.data; + axisSlices[axis] = n; + + _ndarrayOps.default.assign(reshaped.pick(...axisSlices), unraveledChannel); + } + + this.tensor = reshaped; + } + + reshapeTo2DSquare() { + const squareDim = Math.ceil(Math.sqrt(this.tensor.size)); + const reshaped = (0, _ndarray.default)(new this.arrayType(squareDim ** 2), [squareDim, squareDim]); + reshaped.data.set(this.tensor.data); + this.originalShape = this.tensor.shape; + this.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.tensor.shape, true); + this.tensor = reshaped; + this.is2DSquareReshaped = true; + } + + reshapeFrom2DSquare() { + if (!this.is2DSquareReshaped) { + throw new Error('[Tensor] not in reshaped 2D square representation.'); + } + + if (!this.originalShape) { + throw new Error('[Tensor] does not contain originalShape.'); + } + + const size = this.originalShape.reduce((a, b) => a * b, 1); + const reshaped = (0, _ndarray.default)(new this.arrayType(size), this.originalShape); + reshaped.data.set(this.tensor.data.subarray(0, size)); + this.tensor = reshaped; + } + +} + +exports.default = Tensor; \ No newline at end of file diff --git a/keras-js/lib/WebGL2.js b/keras-js/lib/WebGL2.js new file mode 100644 index 0000000000..99f0f4897c --- /dev/null +++ b/keras-js/lib/WebGL2.js @@ -0,0 +1,281 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.MAX_TEXTURE_IMAGE_UNITS = exports.MAX_TEXTURE_SIZE = exports.webgl2 = void 0; +const vertexShaderSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec3 position;\r\nin vec2 texcoord;\r\nout vec2 outTex;\r\n\r\nvoid main () {\r\n gl_Position = vec4(position, 1.0);\r\n\toutTex = texcoord;\r\n}\r\n"; + +class WebGL2 { + constructor() { + this.isSupported = false; + this.vertexShader = null; + + if (typeof window !== 'undefined') { + this.canvas = document.createElement('canvas'); + this.context = this.canvas.getContext('webgl2'); + const gl = this.context; + + if (gl) { + this.isSupported = true; + gl.getExtension('EXT_color_buffer_float'); + this.MAX_TEXTURE_SIZE = gl.getParameter(gl.MAX_TEXTURE_SIZE); + this.MAX_TEXTURE_IMAGE_UNITS = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + this.init(); + } else { + console.log('Unable to initialize WebGL2 -- your browser may not support it.'); + } + } + + this._refs = { + textures: [], + buffers: [] + }; + } + + init() { + this.createCommonVertexShader(); + } + + createCommonVertexShader() { + const gl = this.context; + const vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader, vertexShaderSource); + gl.compileShader(vertexShader); + const success = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS); + + if (!success) { + console.error(gl.getShaderInfoLog(vertexShader)); + gl.deleteShader(vertexShader); + this.isSupported = false; + } + + this.vertexShader = vertexShader; + } + + compileProgram(source) { + const gl = this.context; + const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader, source); + gl.compileShader(fragmentShader); + let success = gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS); + + if (!success) { + console.error(gl.getShaderInfoLog(fragmentShader)); + gl.deleteShader(fragmentShader); + this.isSupported = false; + } + + const program = gl.createProgram(); + gl.attachShader(program, this.vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + success = gl.getProgramParameter(program, gl.LINK_STATUS); + + if (!success) { + console.error(gl.getProgramInfoLog(program)); + this.isSupported = false; + } + + this.setupVertices(program); + return program; + } + + setupVertices(program) { + const gl = this.context; + const position = gl.getAttribLocation(program, 'position'); + const positionVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, positionVertexObj); + this.storeRef('buffer', positionVertexObj); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]), gl.STATIC_DRAW); + gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(position); + const texcoord = gl.getAttribLocation(program, 'texcoord'); + const texcoordVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordVertexObj); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]), gl.STATIC_DRAW); + gl.vertexAttribPointer(texcoord, 2, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(texcoord); + this.storeRef('buffer', texcoordVertexObj); + const indicesVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesVertexObj); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW); + this.storeRef('buffer', indicesVertexObj); + } + + selectProgram(program) { + const gl = this.context; + gl.useProgram(program); + } + + bindUniforms(program, uniforms) { + const gl = this.context; + uniforms.forEach(({ + value, + type, + name + }) => { + const loc = gl.getUniformLocation(program, name); + + if (type === 'float') { + gl.uniform1f(loc, value); + } else if (type === 'int' || type === 'bool') { + gl.uniform1i(loc, value); + } + }); + } + + bindInputTextures(program, inputs, k) { + const gl = this.context; + inputs.forEach(({ + input, + name + }, i) => { + gl.activeTexture(gl.TEXTURE0 + i); + + if (input.glTextureFragments) { + if (input.glTextureFragmentsAsColStack) { + const { + textureTarget + } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat); + gl.bindTexture(textureTarget, input.glTextureFragmentsAsColStack); + } else { + const { + textureTarget + } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat); + gl.bindTexture(textureTarget, input.glTextureFragments[k]); + } + } else { + const { + textureTarget + } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat); + gl.bindTexture(textureTarget, input.glTexture); + } + + gl.uniform1i(gl.getUniformLocation(program, name), i); + }); + } + + bindOutputTexture(outputTexture, shape) { + const gl = this.context; + gl.viewport(0, 0, shape[1], shape[0]); + this.framebuffer = this.framebuffer || gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0); + } + + runProgram({ + program, + output, + inputs, + uniforms, + supportsTextureFragments = false + }) { + if (!program) throw new Error('[WebGL2] missing program'); + if (!output) throw new Error('[WebGL2] missing output'); + if (!inputs) throw new Error('[WebGL2] missing inputs'); + const gl = this.context; + this.selectProgram(program); + + if (uniforms && Array.isArray(uniforms)) { + this.bindUniforms(program, uniforms); + } + + if (output.glTextureFragments) { + if (!supportsTextureFragments) { + throw new Error('[WebGL2] program does not support texture fragments'); + } + + const inputsWithFragments = inputs.filter(obj => obj.input.glTextureFragments && !obj.input.glTextureFragmentsAsColStack); + const numFragments = output.glTextureFragments.length; + + if (inputsWithFragments.some(obj => obj.input.glTextureFragments.length !== numFragments)) { + throw new Error('[WebGL2] number of texture fragments in inputs and output do not match'); + } + + for (let k = 0; k < numFragments; k++) { + this.bindOutputTexture(output.glTextureFragments[k], output.glTextureFragmentShape); + this.bindInputTextures(program, inputs, k); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + } + } else { + this.bindOutputTexture(output.glTexture, output.glTextureShape); + this.bindInputTextures(program, inputs); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + } + } + + readData(shape) { + const gl = this.context; + const buf = new ArrayBuffer(shape[0] * shape[1] * 4 * 4); + const view = new Float32Array(buf); + gl.readPixels(0, 0, shape[1], shape[0], gl.RGBA, gl.FLOAT, view); + const out = []; + + for (let i = 0; i < view.length; i += 4) { + out.push(view[i]); + } + + return new Float32Array(out); + } + + getWebGLTextureOptions(type, format) { + const gl = this.context; + const targetMap = { + '2d': gl.TEXTURE_2D, + '2d_array': gl.TEXTURE_2D_ARRAY, + '3d': gl.TEXTURE_3D + }; + const internalFormatMap = { + float: gl.R32F, + int: gl.R32I + }; + const formatMap = { + float: gl.RED, + int: gl.RED_INTEGER + }; + const typeMap = { + float: gl.FLOAT, + int: gl.INT + }; + const textureTarget = targetMap[type]; + const textureInternalFormat = internalFormatMap[format]; + const textureFormat = formatMap[format]; + const textureType = typeMap[format]; + return { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + }; + } + + storeRef(type, obj) { + if (type === 'texture') { + this._refs.textures.push(obj); + } else if (type === 'buffer') { + this._refs.buffers.push(obj); + } + } + + clearRefs() { + const gl = this.context; + + this._refs.textures.forEach(texture => gl.deleteTexture(texture)); + + this._refs.buffers.forEach(buffer => gl.deleteBuffer(buffer)); + + this._refs = { + textures: [], + buffers: [] + }; + } + +} + +const webgl2 = new WebGL2(); +exports.webgl2 = webgl2; +const MAX_TEXTURE_SIZE = webgl2.MAX_TEXTURE_SIZE; +exports.MAX_TEXTURE_SIZE = MAX_TEXTURE_SIZE; +const MAX_TEXTURE_IMAGE_UNITS = webgl2.MAX_TEXTURE_IMAGE_UNITS; +exports.MAX_TEXTURE_IMAGE_UNITS = MAX_TEXTURE_IMAGE_UNITS; \ No newline at end of file diff --git a/keras-js/lib/activations/elu.js b/keras-js/lib/activations/elu.js new file mode 100644 index 0000000000..477bdb4653 --- /dev/null +++ b/keras-js/lib/activations/elu.js @@ -0,0 +1,25 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = elu; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _elu = (0, _cwise.default)({ + args: ['array', 'scalar'], + body: function (_x, alpha) { + _x = Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1); + } +}); + +function elu(x, opts = {}) { + const { + alpha = 1.0 + } = opts; + + _elu(x.tensor, alpha); +} \ No newline at end of file diff --git a/keras-js/lib/activations/hard_sigmoid.js b/keras-js/lib/activations/hard_sigmoid.js new file mode 100644 index 0000000000..fbb2fb915f --- /dev/null +++ b/keras-js/lib/activations/hard_sigmoid.js @@ -0,0 +1,27 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = hard_sigmoid; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _hard_sigmoid = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x = _x * 0.2 + 0.5; + + if (_x <= 0) { + _x = 0; + } else if (_x >= 1) { + _x = 1; + } + } +}); + +function hard_sigmoid(x) { + _hard_sigmoid(x.tensor); +} \ No newline at end of file diff --git a/keras-js/lib/activations/index.js b/keras-js/lib/activations/index.js new file mode 100644 index 0000000000..01201b9568 --- /dev/null +++ b/keras-js/lib/activations/index.js @@ -0,0 +1,87 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "softmax", { + enumerable: true, + get: function () { + return _softmax.default; + } +}); +Object.defineProperty(exports, "elu", { + enumerable: true, + get: function () { + return _elu.default; + } +}); +Object.defineProperty(exports, "selu", { + enumerable: true, + get: function () { + return _selu.default; + } +}); +Object.defineProperty(exports, "softplus", { + enumerable: true, + get: function () { + return _softplus.default; + } +}); +Object.defineProperty(exports, "softsign", { + enumerable: true, + get: function () { + return _softsign.default; + } +}); +Object.defineProperty(exports, "relu", { + enumerable: true, + get: function () { + return _relu.default; + } +}); +Object.defineProperty(exports, "tanh", { + enumerable: true, + get: function () { + return _tanh.default; + } +}); +Object.defineProperty(exports, "sigmoid", { + enumerable: true, + get: function () { + return _sigmoid.default; + } +}); +Object.defineProperty(exports, "hard_sigmoid", { + enumerable: true, + get: function () { + return _hard_sigmoid.default; + } +}); +Object.defineProperty(exports, "linear", { + enumerable: true, + get: function () { + return _linear.default; + } +}); + +var _softmax = _interopRequireDefault(require("./softmax")); + +var _elu = _interopRequireDefault(require("./elu")); + +var _selu = _interopRequireDefault(require("./selu")); + +var _softplus = _interopRequireDefault(require("./softplus")); + +var _softsign = _interopRequireDefault(require("./softsign")); + +var _relu = _interopRequireDefault(require("./relu")); + +var _tanh = _interopRequireDefault(require("./tanh")); + +var _sigmoid = _interopRequireDefault(require("./sigmoid")); + +var _hard_sigmoid = _interopRequireDefault(require("./hard_sigmoid")); + +var _linear = _interopRequireDefault(require("./linear")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/activations/linear.js b/keras-js/lib/activations/linear.js new file mode 100644 index 0000000000..59fdcc4268 --- /dev/null +++ b/keras-js/lib/activations/linear.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = linear; + +function linear(x) { + return x; +} \ No newline at end of file diff --git a/keras-js/lib/activations/programSources.js b/keras-js/lib/activations/programSources.js new file mode 100644 index 0000000000..928a98fec9 --- /dev/null +++ b/keras-js/lib/activations/programSources.js @@ -0,0 +1,26 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.linear = exports.hard_sigmoid = exports.sigmoid = exports.tanh = exports.relu = exports.softsign = exports.softplus = exports.selu = exports.elu = exports.softmax = void 0; +const softmaxProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float maxval = 0.0;\r\n for (int i = 0; i < int(size[0]); ++i) {\r\n float val = texelFetch(x, ivec2(i, out_y), 0).r;\r\n if (i == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n\r\n float sum = 0.0;\r\n for (int i = 0; i < int(size[0]); ++i) {\r\n float val = texelFetch(x, ivec2(i, out_y), 0).r;\r\n sum += exp(val - maxval);\r\n }\r\n\r\n outColor = exp(texture(x, vec2(outTex.x, outTex.y)) - maxval) / sum;\r\n}\r\n"; +exports.softmax = softmaxProgramSource; +const eluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n float alpha = 1.0;\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0);\r\n}\r\n"; +exports.elu = eluProgramSource; +const seluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n float alpha = 1.6732632423543772848170429916717;\r\n float scale = 1.0507009873554804934193349852946;\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = scale * (max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0));\r\n}\r\n"; +exports.selu = seluProgramSource; +const softplusProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = log(1.0 + exp(texture(x, vec2(outTex.x, outTex.y))));\r\n}\r\n"; +exports.softplus = softplusProgramSource; +const softsignProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n v /= 1.0 + abs(v);\r\n outColor = v;\r\n}\r\n"; +exports.softsign = softsignProgramSource; +const reluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0);\r\n}\r\n"; +exports.relu = reluProgramSource; +const tanhProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = tanh(v);\r\n}\r\n"; +exports.tanh = tanhProgramSource; +const sigmoidProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = 1.0 / (1.0 + exp(-1.0 * texture(x, vec2(outTex.x, outTex.y))));\r\n}\r\n"; +exports.sigmoid = sigmoidProgramSource; +const hardSigmoidProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n v = v * 0.2 + 0.5;\r\n v = max(v, 0.0);\r\n v = min(v, 1.0);\r\n outColor = v;\r\n}\r\n"; +exports.hard_sigmoid = hardSigmoidProgramSource; +const linearProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = texture(x, vec2(outTex.x, outTex.y));\r\n}\r\n"; +exports.linear = linearProgramSource; \ No newline at end of file diff --git a/keras-js/lib/activations/relu.js b/keras-js/lib/activations/relu.js new file mode 100644 index 0000000000..8dc861607a --- /dev/null +++ b/keras-js/lib/activations/relu.js @@ -0,0 +1,38 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = relu; + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _Tensor = _interopRequireDefault(require("../Tensor")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function relu(x, opts = {}) { + const { + alpha = 0, + maxValue = null + } = opts; + let neg; + + if (alpha !== 0) { + neg = new _Tensor.default([], x.tensor.shape); + + _ndarrayOps.default.mins(neg.tensor, x.tensor, 0); + + _ndarrayOps.default.mulseq(neg.tensor, alpha); + } + + _ndarrayOps.default.maxseq(x.tensor, 0); + + if (maxValue) { + _ndarrayOps.default.minseq(x.tensor, maxValue); + } + + if (neg) { + _ndarrayOps.default.addeq(x.tensor, neg.tensor); + } +} \ No newline at end of file diff --git a/keras-js/lib/activations/selu.js b/keras-js/lib/activations/selu.js new file mode 100644 index 0000000000..56ec53c7cd --- /dev/null +++ b/keras-js/lib/activations/selu.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = selu; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _selu = (0, _cwise.default)({ + args: ['array', 'scalar'], + body: function (_x) { + const alpha = 1.6732632423543772848170429916717; + const scale = 1.0507009873554804934193349852946; + _x = scale * (Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1)); + } +}); + +function selu(x) { + _selu(x.tensor); +} \ No newline at end of file diff --git a/keras-js/lib/activations/sigmoid.js b/keras-js/lib/activations/sigmoid.js new file mode 100644 index 0000000000..c5c124653e --- /dev/null +++ b/keras-js/lib/activations/sigmoid.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = sigmoid; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _sigmoid = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x = 1 / (1 + Math.exp(-_x)); + } +}); + +function sigmoid(x) { + _sigmoid(x.tensor); +} \ No newline at end of file diff --git a/keras-js/lib/activations/softmax.js b/keras-js/lib/activations/softmax.js new file mode 100644 index 0000000000..98547ada23 --- /dev/null +++ b/keras-js/lib/activations/softmax.js @@ -0,0 +1,38 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = softmax; + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function softmax(x) { + if (x.tensor.shape.length === 1) { + const maxval = _ndarrayOps.default.sup(x.tensor); + + _ndarrayOps.default.subseq(x.tensor, maxval); + + _ndarrayOps.default.expeq(x.tensor); + + const sum = _ndarrayOps.default.sum(x.tensor); + + _ndarrayOps.default.divseq(x.tensor, sum); + } else if (x.tensor.shape.length === 2) { + for (let i = 0; i < x.tensor.shape[0]; i++) { + const maxval = _ndarrayOps.default.sup(x.tensor.pick(i, null)); + + _ndarrayOps.default.subseq(x.tensor.pick(i, null), maxval); + + _ndarrayOps.default.expeq(x.tensor.pick(i, null)); + + const sum = _ndarrayOps.default.sum(x.tensor.pick(i, null)); + + _ndarrayOps.default.divseq(x.tensor.pick(i, null), sum); + } + } else { + throw new Error(`[activations.softmax] tensor shape ${x.tensor.shape} not supported.`); + } +} \ No newline at end of file diff --git a/keras-js/lib/activations/softplus.js b/keras-js/lib/activations/softplus.js new file mode 100644 index 0000000000..6affd45ff2 --- /dev/null +++ b/keras-js/lib/activations/softplus.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = softplus; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _softplus = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x = Math.log(Math.exp(_x) + 1); + } +}); + +function softplus(x) { + _softplus(x.tensor); +} \ No newline at end of file diff --git a/keras-js/lib/activations/softsign.js b/keras-js/lib/activations/softsign.js new file mode 100644 index 0000000000..a4e81e4f83 --- /dev/null +++ b/keras-js/lib/activations/softsign.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = softsign; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _softsign = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x /= 1 + Math.abs(_x); + } +}); + +function softsign(x) { + _softsign(x.tensor); +} \ No newline at end of file diff --git a/keras-js/lib/activations/tanh.js b/keras-js/lib/activations/tanh.js new file mode 100644 index 0000000000..98f90ed086 --- /dev/null +++ b/keras-js/lib/activations/tanh.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = tanh; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _tanh = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x = Math.tanh(_x); + } +}); + +function tanh(x) { + _tanh(x.tensor); +} \ No newline at end of file diff --git a/keras-js/lib/index.js b/keras-js/lib/index.js new file mode 100644 index 0000000000..1908517b5f --- /dev/null +++ b/keras-js/lib/index.js @@ -0,0 +1,45 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Model", { + enumerable: true, + get: function () { + return _Model.default; + } +}); +Object.defineProperty(exports, "Tensor", { + enumerable: true, + get: function () { + return _Tensor.default; + } +}); +exports.testUtils = exports.layers = exports.activations = exports.GPU_SUPPORT = void 0; + +require("@babel/polyfill"); + +var _Model = _interopRequireDefault(require("./Model")); + +var _Tensor = _interopRequireDefault(require("./Tensor")); + +var _WebGL = require("./WebGL2"); + +var activations = _interopRequireWildcard(require("./activations")); + +exports.activations = activations; + +var layers = _interopRequireWildcard(require("./layers")); + +exports.layers = layers; + +var testUtils = _interopRequireWildcard(require("./utils/testUtils")); + +exports.testUtils = testUtils; + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const GPU_SUPPORT = _WebGL.webgl2.isSupported; +exports.GPU_SUPPORT = GPU_SUPPORT; \ No newline at end of file diff --git a/keras-js/lib/layers/InputLayer.js b/keras-js/lib/layers/InputLayer.js new file mode 100644 index 0000000000..765af7a558 --- /dev/null +++ b/keras-js/lib/layers/InputLayer.js @@ -0,0 +1,83 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); + +var _Layer = _interopRequireDefault(require("../Layer")); + +var _Tensor = _interopRequireDefault(require("../Tensor")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class InputLayer extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'InputLayer'; + const { + shape = [] + } = attrs; + this.shape = attrs.batch_input_shape && attrs.batch_input_shape.length ? attrs.batch_input_shape.slice(1) : shape; + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + if (!(0, _isEqual2.default)(this.inputShape, this.shape)) { + this.throwError(`input tensor shape ${x.tensor.shape} does not match specified shape ${this.shape}.`); + } + + this.output = new _Tensor.default(x.tensor.data, x.tensor.shape); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + this.inputShape = x.tensor.shape; + } else { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + } + + if (!(0, _isEqual2.default)(this.inputShape, this.shape)) { + this.throwError(`input tensor shape ${x.tensor.shape} does not match specified shape ${this.shape}.`); + } + + if (!x.glTexture) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } else if (x.tensor.shape.length > 2) { + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + } + + this.output = x; + } + +} + +exports.default = InputLayer; \ No newline at end of file diff --git a/keras-js/lib/layers/advanced_activations/ELU.js b/keras-js/lib/layers/advanced_activations/ELU.js new file mode 100644 index 0000000000..9ab1acb687 --- /dev/null +++ b/keras-js/lib/layers/advanced_activations/ELU.js @@ -0,0 +1,126 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform float alpha;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0);\r\n}\r\n"; + +class ELU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + + _initialiseProps.call(this); + + this.layerClass = 'ELU'; + const { + alpha = 1.0 + } = attrs; + this.alpha = alpha; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = x; + + this._compute(this.output.tensor, this.alpha); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.alpha, + type: 'float', + name: 'alpha' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = ELU; + +var _initialiseProps = function () { + Object.defineProperty(this, "_compute", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'scalar'], + body: function (_x, alpha) { + _x = Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1); + } + }) + }); +}; \ No newline at end of file diff --git a/keras-js/lib/layers/advanced_activations/LeakyReLU.js b/keras-js/lib/layers/advanced_activations/LeakyReLU.js new file mode 100644 index 0000000000..7c5a9bf761 --- /dev/null +++ b/keras-js/lib/layers/advanced_activations/LeakyReLU.js @@ -0,0 +1,110 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _activations = require("../../activations"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform float alpha;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + alpha * min(v, 0.0);\r\n}\r\n"; + +class LeakyReLU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'LeakyReLU'; + const { + alpha = 0.3 + } = attrs; + this.alpha = alpha; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = x; + (0, _activations.relu)(this.output, { + alpha: this.alpha + }); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.alpha, + type: 'float', + name: 'alpha' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = LeakyReLU; \ No newline at end of file diff --git a/keras-js/lib/layers/advanced_activations/PReLU.js b/keras-js/lib/layers/advanced_activations/PReLU.js new file mode 100644 index 0000000000..7ad0ba94bb --- /dev/null +++ b/keras-js/lib/layers/advanced_activations/PReLU.js @@ -0,0 +1,115 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D alpha;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n vec4 a = texture(alpha, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + a * min(v, 0.0);\r\n}\r\n"; + +class PReLU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + Object.defineProperty(this, "_compute", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array'], + body: function (_x, alpha) { + _x = Math.max(_x, 0) + alpha * Math.min(_x, 0); + } + }) + }); + this.layerClass = 'PReLU'; + this.params = ['alpha']; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = x; + + this._compute(this.output.tensor, this.weights['alpha'].tensor); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.weights['alpha'], + name: 'alpha' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = PReLU; \ No newline at end of file diff --git a/keras-js/lib/layers/advanced_activations/ThresholdedReLU.js b/keras-js/lib/layers/advanced_activations/ThresholdedReLU.js new file mode 100644 index 0000000000..a909c56d3c --- /dev/null +++ b/keras-js/lib/layers/advanced_activations/ThresholdedReLU.js @@ -0,0 +1,126 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform float theta;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = v * float(greaterThan(v, vec4(theta)));\r\n}\r\n"; + +class ThresholdedReLU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + + _initialiseProps.call(this); + + this.layerClass = 'ThresholdedReLU'; + const { + theta = 1 + } = attrs; + this.theta = theta; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = x; + + this._compute(this.output.tensor, this.theta); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.theta, + type: 'float', + name: 'theta' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = ThresholdedReLU; + +var _initialiseProps = function () { + Object.defineProperty(this, "_compute", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'scalar'], + body: function (_x, theta) { + _x = _x * Number(_x > theta); + } + }) + }); +}; \ No newline at end of file diff --git a/keras-js/lib/layers/advanced_activations/index.js b/keras-js/lib/layers/advanced_activations/index.js new file mode 100644 index 0000000000..2acd8b6d96 --- /dev/null +++ b/keras-js/lib/layers/advanced_activations/index.js @@ -0,0 +1,39 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "LeakyReLU", { + enumerable: true, + get: function () { + return _LeakyReLU.default; + } +}); +Object.defineProperty(exports, "PReLU", { + enumerable: true, + get: function () { + return _PReLU.default; + } +}); +Object.defineProperty(exports, "ELU", { + enumerable: true, + get: function () { + return _ELU.default; + } +}); +Object.defineProperty(exports, "ThresholdedReLU", { + enumerable: true, + get: function () { + return _ThresholdedReLU.default; + } +}); + +var _LeakyReLU = _interopRequireDefault(require("./LeakyReLU")); + +var _PReLU = _interopRequireDefault(require("./PReLU")); + +var _ELU = _interopRequireDefault(require("./ELU")); + +var _ThresholdedReLU = _interopRequireDefault(require("./ThresholdedReLU")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/Conv1D.js b/keras-js/lib/layers/convolutional/Conv1D.js new file mode 100644 index 0000000000..3636d59a49 --- /dev/null +++ b/keras-js/lib/layers/convolutional/Conv1D.js @@ -0,0 +1,118 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _Conv2D = _interopRequireDefault(require("./Conv2D")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarraySqueeze = _interopRequireDefault(require("ndarray-squeeze")); + +var _ndarrayUnsqueeze = _interopRequireDefault(require("ndarray-unsqueeze")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Conv1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Conv1D'; + const { + filters = 1, + kernel_size = 1, + strides = 1, + padding = 'valid', + dilation_rate = 1, + activation = 'linear', + use_bias = true + } = attrs; + + if (padding !== 'valid' && padding !== 'same') { + this.throwError('Invalid padding.'); + } + + if (dilation_rate !== 1 && strides !== 1) { + this.throwError('Incompatible combination of dilation_rate with strides.'); + } + + this.use_bias = use_bias; + this.params = this.use_bias ? ['kernel', 'bias'] : ['kernel']; + const conv2dAttrs = { + filters, + kernel_size: [kernel_size, 1], + strides: [strides, 1], + padding, + data_format: 'channels_first', + dilation_rate, + activation, + use_bias + }; + this._conv2dAttrs = conv2dAttrs; + this._conv2d = new _Conv2D.default(Object.assign(conv2dAttrs, { + gpu: attrs.gpu + })); + } + + setWeights(weightsArr) { + weightsArr[0].tensor = (0, _ndarrayUnsqueeze.default)(weightsArr[0].tensor).transpose(2, 1, 0, 3); + + this._conv2d.setWeights(weightsArr); + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const input = new _Tensor.default(x.tensor.data, x.tensor.shape); + input.tensor = (0, _ndarrayUnsqueeze.default)(input.tensor).transpose(0, 2, 1); + + const conv2dOutput = this._conv2d.call(input); + + this.outputShape = [0, 2].map(i => this._conv2d.outputShape[i]); + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor, (0, _ndarraySqueeze.default)(conv2dOutput.tensor).transpose(1, 0, 2)); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const inputShape = x.tensor.shape; + const input = new _Tensor.default([], inputShape); + Object.assign(input, x); + input.glTextureShape = inputShape; + input.is2DReshaped = true; + input.originalShape = [inputShape[0], 1, inputShape[1]]; + input.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(input.originalShape, false, -1); + this.output = this._conv2d.call(input); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Conv1D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/Conv2D.js b/keras-js/lib/layers/convolutional/Conv2D.js new file mode 100644 index 0000000000..f61e049c98 --- /dev/null +++ b/keras-js/lib/layers/convolutional/Conv2D.js @@ -0,0 +1,457 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const mapInputFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(indexMap, 0);\r\n int out_x = int(float(outputSize[0]) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n int fragmentIndex = int(floor(float(rowIndex) / float(inputSize[1])));\r\n rowIndex = int(mod(float(rowIndex), float(inputSize[1])));\r\n colIndex = fragmentIndex * inputCols + colIndex;\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class Conv2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Conv2D'; + const { + filters = 1, + kernel_size = [3, 3], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + dilation_rate = [1, 1], + activation = 'linear', + use_bias = true + } = attrs; + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size]; + } else { + this.kernelShape = [filters, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else { + this.strides = [strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format; + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + if (Array.isArray(dilation_rate)) { + this.dilationRate = dilation_rate; + } else { + this.dilationRate = [dilation_rate, dilation_rate]; + } + + if ((this.dilationRate[0] !== 1 || this.dilationRate[1] !== 1) && (this.strides[0] !== 1 || this.strides[1] !== 1)) { + this.throwError(`Incompatible combination of dilation_rate with strides.`); + } + + this.activation = activation; + this.activationFunc = activations[activation]; + this.useBias = use_bias; + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel']; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + this.mapInputFragmentsProgram = _WebGL.webgl2.compileProgram(mapInputFragmentsProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0); + } + + super.setWeights(weightsArr, false); + + this._w2row(); + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat; + this.weights['kernel'].createGLTexture({ + type: '2d', + format: 'float' + }); + + if (this.useBias) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + const inputRows = inputShape[0]; + const inputCols = inputShape[1]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + const outputRows = this.padding === 'same' ? Math.floor((inputRows + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputRows - nbRowDilated + this.strides[0]) / this.strides[0]); + const outputCols = this.padding === 'same' ? Math.floor((inputCols + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputCols - nbColDilated + this.strides[1]) / this.strides[1]); + const outputChannels = nbFilter; + const paddingRow = this.padding === 'same' ? Math.max(0, Math.floor((outputRows - 1) * this.strides[0] + nbRowDilated - inputRows)) : 0; + const paddingCol = this.padding === 'same' ? Math.max(0, Math.floor((outputCols - 1) * this.strides[1] + nbColDilated - inputCols)) : 0; + const paddingRowBefore = Math.floor(paddingRow / 2); + const paddingRowAfter = paddingRow - paddingRowBefore; + const paddingColBefore = Math.floor(paddingCol / 2); + const paddingColAfter = paddingCol - paddingColBefore; + this.outputShape = [outputRows, outputCols, outputChannels]; + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]; + } + + _padInput(x, padValue = 0) { + if (this.padding === 'same') { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + const newRows = inputRows + paddingRowBefore + paddingRowAfter; + const newCols = inputCols + paddingColBefore + paddingColAfter; + + const _x = new _Tensor.default([], [newRows, newCols, inputChannels]); + + if (padValue !== 0) { + _ndarrayOps.default.assigns(_x.tensor, padValue); + } + + _ndarrayOps.default.assign(_x.tensor.hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels).lo(paddingRowBefore, paddingColBefore, 0), x.tensor); + + return _x; + } + + return x; + } + + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const nbRow = this.kernelShape[1]; + const nbCol = this.kernelShape[2]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const patchLen = nbRow * nbCol * inputChannels; + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + + if (!this.imColsMat) { + this.imColsMat = new _Tensor.default([], [nbPatches, patchLen]); + } + + if (nbRowDilated === 1 && nbColDilated === 1 && this.strides[0] === 1 && this.strides[1] === 1) { + this.imColsMat.replaceTensorData(x.tensor.data); + return this.imColsMat; + } + + const patch = new _Tensor.default([], [nbRow, nbCol, inputChannels]); + let offset = 0; + + for (let i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbColDilated; j <= limit; j += this.strides[1]) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + nbRowDilated, j + nbColDilated, inputChannels).lo(i, j, 0).step(this.dilationRate[0], this.dilationRate[1], 1)); + + this.imColsMat.tensor.data.set(patch.tensor.data, offset); + offset += patchLen; + } + } + + return this.imColsMat; + } + + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[2]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const patchLen = nbRow * nbCol * inputChannels; + this.wRowsMat = new _Tensor.default([], [patchLen, nbFilter]); + const patch = new _Tensor.default([], [nbRow, nbCol, inputChannels]); + const patchRaveled = new _Tensor.default([], [patchLen]); + + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, null, n)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.wRowsMat.tensor.pick(null, n), patchRaveled.tensor); + } + + return this.wRowsMat; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._im2col(x); + + const nbFilter = this.kernelShape[0]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const matMul = new _Tensor.default([], [nbPatches, nbFilter]); + + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assigns(matMul.tensor.pick(null, n), this.weights['bias'].tensor.get(n)); + } + } + + (0, _ndarrayGemm.default)(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1); + this.output = new _Tensor.default([], this.outputShape); + let outputChannelRaveled = new _Tensor.default([], [outputRows * outputCols]); + let outputChannel = new _Tensor.default([], [outputRows, outputCols]); + + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(outputChannelRaveled.tensor, matMul.tensor.pick(null, n)); + + outputChannel.replaceTensorData(outputChannelRaveled.tensor.data); + + _ndarrayOps.default.assign(this.output.tensor.pick(null, null, n), outputChannel.tensor); + } + + this.activationFunc(this.output); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + let [inputRows, inputCols, inputChannels] = this.inputShape; + let indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + + if (this.padding === 'same') { + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + inputRows = inputRows + paddingRowBefore + paddingRowAfter; + inputCols = inputCols + paddingColBefore + paddingColAfter; + const padValue = -1; + indices = this._padInput(indices, padValue); + } + + const nbRow = this.kernelShape[1]; + const nbCol = this.kernelShape[2]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const patchLen = nbRow * nbCol * inputChannels; + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + this.indexMap = new _Tensor.default([], [nbPatches, patchLen], { + type: Int32Array + }); + const indicesPatch = new _Tensor.default([], [nbRow, nbCol, inputChannels]); + let offset = 0; + + for (let i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbColDilated; j <= limit; j += this.strides[1]) { + _ndarrayOps.default.assign(indicesPatch.tensor, indices.tensor.hi(i + nbRowDilated, j + nbColDilated, inputChannels).lo(i, j, 0).step(this.dilationRate[0], this.dilationRate[1], 1)); + + this.indexMap.tensor.data.set(indicesPatch.tensor.data, offset); + offset += patchLen; + } + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + let outputTextureShape; + + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(x.indicesForReshaped); + + outputTextureShape = [this.indexMap.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } else { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._im2col(x); + + this.imColsMat.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + outputTextureShape = [this.imColsMat.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new _Tensor.default([], outputTextureShape); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputPreactiv.is2DReshaped = true; + this.outputPreactiv.originalShape = this.outputShape; + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (!this.output) { + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (x.is2DReshaped || x.is2DSquareReshaped) { + const hasFragments = Boolean(x.glTextureFragments); + + if (hasFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + } + + if (!this.convProgram) { + const convProgramSource = (0, _createGLSLProgram.default)('conv2d', this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, x.glTextureFragmentShape ? x.glTextureFragmentShape : x.glTextureShape, this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, this.useBias, hasFragments); + this.convProgram = _WebGL.webgl2.compileProgram(convProgramSource); + } + + _WebGL.webgl2.runProgram({ + program: this.convProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }, { + input: this.weights['kernel'], + name: 'kernel' + }, ...(this.useBias ? [{ + input: this.weights['bias'], + name: 'bias' + }] : [])], + supportsTextureFragments: true + }); + + if (hasFragments) { + x.removeGLTextureFragmentsAsColStack(); + } + } else { + const matMulInputs = [{ + input: this.imColsMat, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }]; + + if (this.useBias) { + matMulInputs.push({ + input: this.weights['bias'], + name: 'C' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ + value: this.useBias ? 1 : 0, + type: 'bool', + name: 'addC' + }], + supportsTextureFragments: true + }); + } + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + +} + +exports.default = Conv2D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/Conv2DTranspose.js b/keras-js/lib/layers/convolutional/Conv2DTranspose.js new file mode 100644 index 0000000000..4a91d95b1c --- /dev/null +++ b/keras-js/lib/layers/convolutional/Conv2DTranspose.js @@ -0,0 +1,471 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _cwise = _interopRequireDefault(require("cwise")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; +const assignToRowIndicesMap = (0, _cwise.default)({ + args: [{ + blockIndices: -1 + }, 'scalar', 'scalar'], + body: function (x, rowIndex, size) { + for (let i = 0; i < size; i++) { + if (x[i] === -1) { + x[i] = rowIndex; + break; + } + } + } +}); +const assignToColIndicesMap = (0, _cwise.default)({ + args: [{ + blockIndices: -1 + }, 'array', 'scalar'], + body: function (x, colIndex, size) { + for (let i = 0; i < size; i++) { + if (x[i] === -1) { + x[i] = colIndex; + break; + } + } + } +}); + +class Conv2DTranspose extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Conv2DTranspose'; + const { + filters = 1, + kernel_size = [3, 3], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + activation = 'linear', + use_bias = true + } = attrs; + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size]; + } else { + this.kernelShape = [filters, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else { + this.strides = [strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format; + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + this.activation = activation; + this.activationFunc = activations[activation]; + this.useBias = use_bias; + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel']; + + if (this.gpu) { + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0); + } + + super.setWeights(weightsArr, false); + + this._w2row(); + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat; + this.weights['kernel'].createGLTexture({ + type: '2d', + format: 'float' + }); + + if (this.useBias) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.outputPadding) { + return; + } + + const inputRows = inputShape[0]; + const inputCols = inputShape[1]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const outputRows = this.padding === 'same' ? inputRows * this.strides[0] : inputRows * this.strides[0] + Math.max(nbRow - this.strides[0], 0); + const outputCols = this.padding === 'same' ? inputCols * this.strides[1] : inputCols * this.strides[1] + Math.max(nbCol - this.strides[1], 0); + const outputChannels = nbFilter; + const paddingRow = this.padding === 'same' ? Math.max(0, Math.floor((inputRows - 1) * this.strides[0] + nbRow - outputRows)) : 0; + const paddingCol = this.padding === 'same' ? Math.max(0, Math.floor((inputCols - 1) * this.strides[1] + nbCol - outputCols)) : 0; + const paddingRowBefore = Math.floor(paddingRow / 2); + const paddingRowAfter = paddingRow - paddingRowBefore; + const paddingColBefore = Math.floor(paddingCol / 2); + const paddingColAfter = paddingCol - paddingColBefore; + this.outputShape = [outputRows, outputCols, outputChannels]; + this.outputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]; + } + + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + + if (!this.imColsMat) { + this.imColsMat = new _Tensor.default([], [inputRows * inputCols, inputChannels]); + } + + const channelRaveled = new _Tensor.default([], [inputRows * inputCols]); + const channel = new _Tensor.default([], [inputRows, inputCols]); + + for (let c = 0; c < inputChannels; c++) { + _ndarrayOps.default.assign(channel.tensor, x.tensor.pick(null, null, c)); + + channelRaveled.replaceTensorData(channel.tensor.data); + + _ndarrayOps.default.assign(this.imColsMat.tensor.pick(null, c), channelRaveled.tensor); + } + + return this.imColsMat; + } + + _w2row() { + const [nbRow, nbCol, nbFilter, inputChannels] = this.weights['kernel'].tensor.shape; + this.wRowsMat = new _Tensor.default([], [inputChannels, nbRow * nbCol * nbFilter]); + const channelRaveled = new _Tensor.default([], [nbRow * nbCol * nbFilter]); + const channel = new _Tensor.default([], [nbRow, nbCol, nbFilter]); + + for (let c = 0; c < inputChannels; c++) { + _ndarrayOps.default.assign(channel.tensor, this.weights['kernel'].tensor.pick(null, null, null, c)); + + channelRaveled.replaceTensorData(channel.tensor.data); + + _ndarrayOps.default.assign(this.wRowsMat.tensor.pick(c, null), channelRaveled.tensor); + } + + return this.wRowsMat; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + this._im2col(x); + + const inputRows = x.tensor.shape[0]; + const inputCols = x.tensor.shape[1]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const matMul = new _Tensor.default([], [inputRows * inputCols, nbRow * nbCol * nbFilter]); + (0, _ndarrayGemm.default)(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1); + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.outputPadding; + this.output = new _Tensor.default([], this.outputShape); + let outputPadded = new _Tensor.default([], [this.outputShape[0] + paddingRowBefore + paddingRowAfter, this.outputShape[1] + paddingColBefore + paddingColAfter, this.outputShape[2]]); + const patchShape = [nbRow, nbCol, nbFilter]; + let patch = new _Tensor.default([], patchShape); + let patchRaveled = new _Tensor.default([], [nbRow * nbCol * nbFilter]); + let index = 0; + + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + _ndarrayOps.default.assign(patchRaveled.tensor, matMul.tensor.pick(index, null)); + + patch.replaceTensorData(patchRaveled.tensor.data); + const iOutPos = i * this.strides[0]; + const jOutPos = j * this.strides[1]; + + _ndarrayOps.default.addeq(outputPadded.tensor.hi(iOutPos + nbRow, jOutPos + nbCol, this.outputShape[2]).lo(iOutPos, jOutPos, 0), patch.tensor); + + index += 1; + } + } + + _ndarrayOps.default.assign(this.output.tensor, outputPadded.tensor.hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, this.outputShape[2]).lo(paddingRowBefore, paddingColBefore, 0)); + + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.addseq(this.output.tensor.pick(null, null, n), this.weights['bias'].tensor.get(n)); + } + } + + this.activationFunc(this.output); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const inputRows = this.inputShape[0]; + const inputCols = this.inputShape[1]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.outputPadding; + const effectiveKernelSize = (nbRow - this.strides[0] + 1) * (nbCol - this.strides[1] + 1); + const indicesMapShape = [this.outputShape[0], this.outputShape[1], effectiveKernelSize]; + const indicesMapShapePadded = [this.outputShape[0] + paddingRowBefore + paddingRowAfter, this.outputShape[1] + paddingColBefore + paddingColAfter, effectiveKernelSize]; + const outputRowIndicesMap = new _Tensor.default([], indicesMapShape, { + type: Int32Array + }); + const outputColIndicesMap = new _Tensor.default([], indicesMapShape, { + type: Int32Array + }); + const outputRowIndicesMapPadded = new _Tensor.default([], indicesMapShapePadded, { + type: Int32Array + }); + const outputColIndicesMapPadded = new _Tensor.default([], indicesMapShapePadded, { + type: Int32Array + }); + + _ndarrayOps.default.assigns(outputRowIndicesMap.tensor, -1); + + _ndarrayOps.default.assigns(outputColIndicesMap.tensor, -1); + + _ndarrayOps.default.assigns(outputRowIndicesMapPadded.tensor, -1); + + _ndarrayOps.default.assigns(outputColIndicesMapPadded.tensor, -1); + + const matMulColIndicesPatch = new _Tensor.default([], [nbRow, nbCol, nbFilter], { + type: Int32Array + }); + + for (let i = 0; i < nbRow * nbCol * nbFilter; i++) { + matMulColIndicesPatch.tensor.data[i] = i; + } + + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + const matMulRowIndex = i * inputCols + j; + const iOutPos = i * this.strides[0]; + const jOutPos = j * this.strides[1]; + assignToRowIndicesMap(outputRowIndicesMapPadded.tensor.hi(iOutPos + nbRow, jOutPos + nbCol, effectiveKernelSize).lo(iOutPos, jOutPos, 0), matMulRowIndex, effectiveKernelSize); + assignToColIndicesMap(outputColIndicesMapPadded.tensor.hi(iOutPos + nbRow, jOutPos + nbCol, effectiveKernelSize).lo(iOutPos, jOutPos, 0), matMulColIndicesPatch.tensor.pick(null, null, 0), effectiveKernelSize); + } + } + + _ndarrayOps.default.assign(outputRowIndicesMap.tensor, outputRowIndicesMapPadded.tensor.hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, effectiveKernelSize).lo(paddingRowBefore, paddingColBefore, 0)); + + _ndarrayOps.default.assign(outputColIndicesMap.tensor, outputColIndicesMapPadded.tensor.hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, effectiveKernelSize).lo(paddingRowBefore, paddingColBefore, 0)); + + const tiledIndicesMapShape = [this.outputShape[0] * this.outputShape[1], effectiveKernelSize]; + this.indexMap = new _Tensor.default([], tiledIndicesMapShape, { + type: Int32Array + }); + const channelData = new _Tensor.default([], [effectiveKernelSize], { + type: Int32Array + }); + + for (let i = 0; i < this.outputShape[0]; i++) { + for (let j = 0; j < this.outputShape[1]; j++) { + for (let k = 0; k < effectiveKernelSize; k++) { + const rowIndex = outputRowIndicesMap.tensor.get(i, j, k); + const colIndex = outputColIndicesMap.tensor.get(i, j, k); + + if (rowIndex !== -1 && colIndex !== -1) { + channelData.tensor.set(k, rowIndex * this.weights['kernel'].glTextureShape[1] + colIndex); + } else { + channelData.tensor.set(k, -1); + } + } + + _ndarrayOps.default.assign(this.indexMap.tensor.pick(i * this.outputShape[1] + j, null), channelData.tensor); + } + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + + this._calcOutputShape(this.inputShape); + } else { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + this._im2col(x); + + this.imColsMat.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.imColsMat; + + if (!this.matMulResult) { + const outputTextureShape = [input.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + this.matMulResult = new _Tensor.default([], outputTextureShape); + this.matMulResult.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + const outputTextureShape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]]; + this.outputPreactiv = new _Tensor.default([], outputTextureShape); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputPreactiv.is2DReshaped = true; + this.outputPreactiv.originalShape = this.outputShape; + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (!this.output) { + const outputTextureShape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]]; + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.matMulResult, + inputs: [{ + input: input, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }], + supportsTextureFragments: true + }); + + this._createIndexMap(); + + const hasFragments = Boolean(this.matMulResult.glTextureFragments); + + if (hasFragments) { + this.matMulResult.convert2DRowFragmentedGLTextureToColStack(); + } + + if (!this.convTransposeProgram) { + const convTransposeProgramSource = (0, _createGLSLProgram.default)('conv2dTranspose', this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, this.matMulResult.glTextureFragmentShape ? this.matMulResult.glTextureFragmentShape : this.matMulResult.glTextureShape, this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, this.useBias, hasFragments); + this.convTransposeProgram = _WebGL.webgl2.compileProgram(convTransposeProgramSource); + } + + _WebGL.webgl2.runProgram({ + program: this.convTransposeProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [{ + input: this.matMulResult, + name: 'matMulResult' + }, { + input: this.indexMap, + name: 'indexMap' + }, ...(this.useBias ? [{ + input: this.weights['bias'], + name: 'bias' + }] : [])], + supportsTextureFragments: true + }); + + if (hasFragments) { + this.matMulResult.removeGLTextureFragmentsAsColStack(); + } + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + +} + +exports.default = Conv2DTranspose; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/Conv3D.js b/keras-js/lib/layers/convolutional/Conv3D.js new file mode 100644 index 0000000000..50c83a0686 --- /dev/null +++ b/keras-js/lib/layers/convolutional/Conv3D.js @@ -0,0 +1,476 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const mapInputFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(indexMap, 0);\r\n int out_x = int(float(outputSize[0]) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n int fragmentIndex = int(floor(float(rowIndex) / float(inputSize[1])));\r\n rowIndex = int(mod(float(rowIndex), float(inputSize[1])));\r\n colIndex = fragmentIndex * inputCols + colIndex;\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class Conv3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Conv3D'; + const { + filters = 1, + kernel_size = [1, 1, 1], + strides = [1, 1, 1], + padding = 'valid', + data_format = 'channels_last', + dilation_rate = [1, 1, 1], + activation = 'linear', + use_bias = true + } = attrs; + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size]; + } else { + this.kernelShape = [filters, kernel_size, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else { + this.strides = [strides, strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format; + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + if (Array.isArray(dilation_rate)) { + this.dilationRate = dilation_rate; + } else { + this.dilationRate = [dilation_rate, dilation_rate, dilation_rate]; + } + + if ((this.dilationRate[0] !== 1 || this.dilationRate[1] !== 1 || this.dilationRate[2] !== 1) && (this.strides[0] !== 1 || this.strides[1] !== 1 || this.strides[2] !== 1)) { + this.throwError('Incompatible combination of dilation_rate with strides.'); + } + + this.activation = activation; + this.activationFunc = activations[activation]; + this.useBias = use_bias; + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel']; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + this.mapInputFragmentsProgram = _WebGL.webgl2.compileProgram(mapInputFragmentsProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 4, 1, 0); + } + + super.setWeights(weightsArr, false); + + this._w2row(); + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat; + this.weights['kernel'].createGLTexture({ + type: '2d', + format: 'float' + }); + + if (this.useBias) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + const inputDim1 = inputShape[0]; + const inputDim2 = inputShape[1]; + const inputDim3 = inputShape[2]; + const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape; + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1); + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1); + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1); + const outputDim1 = this.padding === 'same' ? Math.floor((inputDim1 + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputDim1 - kernelDim1Dilated + this.strides[0]) / this.strides[0]); + const outputDim2 = this.padding === 'same' ? Math.floor((inputDim2 + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputDim2 - kernelDim2Dilated + this.strides[1]) / this.strides[1]); + const outputDim3 = this.padding === 'same' ? Math.floor((inputDim3 + this.strides[2] - 1) / this.strides[2]) : Math.floor((inputDim3 - kernelDim3Dilated + this.strides[2]) / this.strides[2]); + const outputChannels = nbFilter; + const paddingDim1 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim1 - 1) * this.strides[0] + kernelDim1Dilated - inputDim1)) : 0; + const paddingDim2 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim2 - 1) * this.strides[1] + kernelDim2Dilated - inputDim2)) : 0; + const paddingDim3 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim3 - 1) * this.strides[2] + kernelDim3Dilated - inputDim3)) : 0; + const paddingDim1Before = Math.floor(paddingDim1 / 2); + const paddingDim1After = paddingDim1 - paddingDim1Before; + const paddingDim2Before = Math.floor(paddingDim2 / 2); + const paddingDim2After = paddingDim2 - paddingDim2Before; + const paddingDim3Before = Math.floor(paddingDim3 / 2); + const paddingDim3After = paddingDim3 - paddingDim3Before; + this.outputShape = [outputDim1, outputDim2, outputDim3, outputChannels]; + this.inputPadding = [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After]; + } + + _padInput(x, padValue = 0) { + if (this.padding === 'same') { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + const newDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + const newDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + const newDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + + const _x = new _Tensor.default([], [newDim1, newDim2, newDim3, inputChannels]); + + if (padValue !== 0) { + _ndarrayOps.default.assigns(_x.tensor, padValue); + } + + _ndarrayOps.default.assign(_x.tensor.hi(inputDim1 + paddingDim1Before, inputDim2 + paddingDim2Before, inputDim3 + paddingDim3Before, inputChannels).lo(paddingDim1Before, paddingDim2Before, paddingDim3Before, 0), x.tensor); + + return _x; + } + + return x; + } + + _vol2col(x) { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + const kernelDim1 = this.kernelShape[1]; + const kernelDim2 = this.kernelShape[2]; + const kernelDim3 = this.kernelShape[3]; + const outputDim1 = this.outputShape[0]; + const outputDim2 = this.outputShape[1]; + const outputDim3 = this.outputShape[2]; + const nbPatches = outputDim1 * outputDim2 * outputDim3; + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels; + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1); + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1); + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1); + + if (!this.volColsMat) { + this.volColsMat = new _Tensor.default([], [nbPatches, patchLen]); + } + + if (kernelDim1Dilated === 1 && kernelDim2Dilated === 1 && kernelDim3Dilated === 1 && this.strides[0] === 1 && this.strides[1] === 1 && this.strides[2] === 1) { + this.volColsMat.replaceTensorData(x.tensor.data); + return this.volColsMat; + } + + const patch = new _Tensor.default([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]); + let offset = 0; + + for (let i = 0, limit = inputDim1 - kernelDim1Dilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - kernelDim2Dilated; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - kernelDim3Dilated; k <= limit; k += this.strides[2]) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + kernelDim1Dilated, j + kernelDim2Dilated, k + kernelDim3Dilated, inputChannels).lo(i, j, k, 0).step(this.dilationRate[0], this.dilationRate[1], this.dilationRate[2], 1)); + + this.volColsMat.tensor.data.set(patch.tensor.data, offset); + offset += patchLen; + } + } + } + + return this.volColsMat; + } + + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[3]; + const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape; + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels; + this.wRowsMat = new _Tensor.default([], [patchLen, nbFilter]); + const patch = new _Tensor.default([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]); + const patchRaveled = new _Tensor.default([], [patchLen]); + + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, null, null, n)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.wRowsMat.tensor.pick(null, n), patchRaveled.tensor); + } + + return this.wRowsMat; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._vol2col(x); + + const nbFilter = this.kernelShape[0]; + const outputDim1 = this.outputShape[0]; + const outputDim2 = this.outputShape[1]; + const outputDim3 = this.outputShape[2]; + const nbPatches = outputDim1 * outputDim2 * outputDim3; + const matMul = new _Tensor.default([], [nbPatches, nbFilter]); + + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assigns(matMul.tensor.pick(null, n), this.weights['bias'].tensor.get(n)); + } + } + + (0, _ndarrayGemm.default)(matMul.tensor, this.volColsMat.tensor, this.wRowsMat.tensor, 1, 1); + this.output = new _Tensor.default([], this.outputShape); + let outputChannelRaveled = new _Tensor.default([], [outputDim1 * outputDim2 * outputDim3]); + let outputChannel = new _Tensor.default([], [outputDim1, outputDim2, outputDim3]); + + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(outputChannelRaveled.tensor, matMul.tensor.pick(null, n)); + + outputChannel.replaceTensorData(outputChannelRaveled.tensor.data); + + _ndarrayOps.default.assign(this.output.tensor.pick(null, null, null, n), outputChannel.tensor); + } + + this.activationFunc(this.output); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + let [inputDim1, inputDim2, inputDim3, inputChannels] = this.inputShape; + let indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + + if (this.padding === 'same') { + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + inputDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + inputDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + inputDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + const padValue = -1; + indices = this._padInput(indices, padValue); + } + + const kernelDim1 = this.kernelShape[1]; + const kernelDim2 = this.kernelShape[2]; + const kernelDim3 = this.kernelShape[3]; + const outputDim1 = this.outputShape[0]; + const outputDim2 = this.outputShape[1]; + const outputDim3 = this.outputShape[2]; + const nbPatches = outputDim1 * outputDim2 * outputDim3; + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels; + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1); + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1); + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1); + this.indexMap = new _Tensor.default([], [nbPatches, patchLen], { + type: Int32Array + }); + const indicesPatch = new _Tensor.default([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]); + let offset = 0; + + for (let i = 0, limit = inputDim1 - kernelDim1Dilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - kernelDim2Dilated; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - kernelDim3Dilated; k <= limit; k += this.strides[2]) { + _ndarrayOps.default.assign(indicesPatch.tensor, indices.tensor.hi(i + kernelDim1Dilated, j + kernelDim2Dilated, k + kernelDim3Dilated, inputChannels).lo(i, j, k, 0).step(this.dilationRate[0], this.dilationRate[1], this.dilationRate[2], 1)); + + this.indexMap.tensor.data.set(indicesPatch.tensor.data, offset); + offset += patchLen; + } + } + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + let outputTextureShape; + + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(x.indicesForReshaped); + + outputTextureShape = [this.indexMap.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } else { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._vol2col(x); + + this.volColsMat.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + outputTextureShape = [this.volColsMat.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new _Tensor.default([], outputTextureShape); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputPreactiv.is2DReshaped = true; + this.outputPreactiv.originalShape = this.outputShape; + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (!this.output) { + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (x.is2DReshaped || x.is2DSquareReshaped) { + const hasFragments = Boolean(x.glTextureFragments); + + if (hasFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + } + + if (!this.convProgram) { + const convProgramSource = (0, _createGLSLProgram.default)('conv2d', this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, x.glTextureFragmentShape ? x.glTextureFragmentShape : x.glTextureShape, this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, this.useBias, hasFragments); + this.convProgram = _WebGL.webgl2.compileProgram(convProgramSource); + } + + _WebGL.webgl2.runProgram({ + program: this.convProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }, { + input: this.weights['kernel'], + name: 'kernel' + }, ...(this.useBias ? [{ + input: this.weights['bias'], + name: 'bias' + }] : [])], + supportsTextureFragments: true + }); + + if (hasFragments) { + x.removeGLTextureFragmentsAsColStack(); + } + } else { + const matMulInputs = [{ + input: this.volColsMat, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }]; + + if (this.useBias) { + matMulInputs.push({ + input: this.weights['bias'], + name: 'C' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ + value: this.useBias ? 1 : 0, + type: 'bool', + name: 'addC' + }], + supportsTextureFragments: true + }); + } + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + } + +} + +exports.default = Conv3D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/Cropping1D.js b/keras-js/lib/layers/convolutional/Cropping1D.js new file mode 100644 index 0000000000..15d96ade58 --- /dev/null +++ b/keras-js/lib/layers/convolutional/Cropping1D.js @@ -0,0 +1,143 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Cropping1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Cropping1D'; + const { + cropping = [0, 0] + } = attrs; + + if (Array.isArray(cropping)) { + this.cropping = cropping; + } else { + this.cropping = [cropping, cropping]; + } + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] - this.cropping[0] - this.cropping[1], this.inputShape[1]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor, x.tensor.hi(this.inputShape[0] - this.cropping[1], this.inputShape[2]).lo(this.cropping[0], 0)); + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(null, j), j); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = [this.cropping[0], 0]; + const sliceEnd = [this.inputShape[0] - this.cropping[1], this.inputShape[2]]; + + _ndarrayOps.default.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)); + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] - this.cropping[0] - this.cropping[1], this.inputShape[1]]; + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Cropping1D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/Cropping2D.js b/keras-js/lib/layers/convolutional/Cropping2D.js new file mode 100644 index 0000000000..eb9825d794 --- /dev/null +++ b/keras-js/lib/layers/convolutional/Cropping2D.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Cropping2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Cropping2D'; + const { + cropping = [[0, 0], [0, 0]], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(cropping)) { + if (Array.isArray(cropping[0])) { + this.cropping = cropping; + } else { + this.cropping = [[cropping[0], cropping[0]], [cropping[1], cropping[1]]]; + } + } else { + this.cropping = [[cropping, cropping], [cropping, cropping]]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[2]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor, x.tensor.hi(this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2]).lo(this.cropping[0][0], this.cropping[1][0], 0)); + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1); + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = this.dataFormat === 'channels_first' ? [0, this.cropping[0][0], this.cropping[1][0]] : [this.cropping[0][0], this.cropping[1][0], 0]; + const sliceEnd = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][1]] : [this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2]]; + + _ndarrayOps.default.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)); + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][0] - this.cropping[1][1]] : [this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[2]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = Cropping2D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/Cropping3D.js b/keras-js/lib/layers/convolutional/Cropping3D.js new file mode 100644 index 0000000000..a28b472fa8 --- /dev/null +++ b/keras-js/lib/layers/convolutional/Cropping3D.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Cropping3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Cropping3D'; + const { + cropping = [[0, 0], [0, 0], [0, 0]], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(cropping)) { + if (Array.isArray(cropping[0])) { + this.cropping = cropping; + } else { + this.cropping = [[cropping[0], cropping[0]], [cropping[1], cropping[1]], [cropping[2], cropping[2]]]; + } + } else { + this.cropping = [[cropping, cropping], [cropping, cropping], [cropping, cropping]]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[2] - this.cropping[2][0] - this.cropping[2][1], this.inputShape[3]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor, x.tensor.hi(this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2] - this.cropping[2][1], this.inputShape[3]).lo(this.cropping[0][0], this.cropping[1][0], this.cropping[2][0], 0)); + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2); + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = this.dataFormat === 'channels_first' ? [0, this.cropping[0][0], this.cropping[1][0], this.cropping[2][0]] : [this.cropping[0][0], this.cropping[1][0], this.cropping[2][0], 0]; + const sliceEnd = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][1], this.inputShape[3] - this.cropping[2][1]] : [this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2] - this.cropping[2][1], this.inputShape[3]]; + + _ndarrayOps.default.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)); + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[3] - this.cropping[2][0] - this.cropping[2][1]] : [this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[2] - this.cropping[2][0] - this.cropping[2][1], this.inputShape[3]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = Cropping3D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/SeparableConv2D.js b/keras-js/lib/layers/convolutional/SeparableConv2D.js new file mode 100644 index 0000000000..1b557064c8 --- /dev/null +++ b/keras-js/lib/layers/convolutional/SeparableConv2D.js @@ -0,0 +1,366 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var _Conv2D = _interopRequireDefault(require("./Conv2D")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class _DepthwiseConv2D extends _Conv2D.default { + constructor(attrs = {}) { + super(attrs); + } + + _calcOutputShape(inputShape) { + super._calcOutputShape(inputShape); + + const nbFilter = this.kernelShape[0]; + const inputChannels = inputShape[2]; + this.outputShape[2] = nbFilter * inputChannels; + } + + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const nbRow = this.kernelShape[1]; + const nbCol = this.kernelShape[2]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const patchLen = nbRow * nbCol; + + if (!this.imColsMat) { + this.imColsMat = new _Tensor.default([], [nbPatches * inputChannels, patchLen]); + } + + let patch = new _Tensor.default([], [nbRow, nbCol, 1]); + let offset = 0; + + for (let c = 0; c < inputChannels; c++) { + for (let i = 0, limit = inputRows - nbRow; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbCol; j <= limit; j += this.strides[1]) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + nbRow, j + nbCol, c + 1).lo(i, j, c)); + + this.imColsMat.tensor.data.set(patch.tensor.data, offset); + offset += patchLen; + } + } + } + + return this.imColsMat; + } + + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[2]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const patchLen = nbRow * nbCol; + this.wRowsMat = new _Tensor.default([], [patchLen, nbFilter * inputChannels]); + let patch = new _Tensor.default([], [nbRow, nbCol]); + let patchRaveled = new _Tensor.default([], [patchLen]); + let p = 0; + + for (let c = 0; c < inputChannels; c++) { + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, c, n)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.wRowsMat.tensor.pick(null, p), patchRaveled.tensor); + + p += 1; + } + } + + return this.wRowsMat; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._im2col(x); + + const nbFilter = this.kernelShape[0]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const inputChannels = this.inputShape[2]; + const matMul = new _Tensor.default([], [nbPatches * inputChannels, nbFilter * inputChannels]); + (0, _ndarrayGemm.default)(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1); + this.output = new _Tensor.default([], this.outputShape); + const outputDataLength = outputRows * outputCols * nbFilter * inputChannels; + let dataFiltered = new Float32Array(outputDataLength); + + for (let c = 0; c < inputChannels; c++) { + for (let n = c * outputDataLength + c * nbFilter; n < (c + 1) * outputDataLength; n += nbFilter * inputChannels) { + for (let m = 0; m < nbFilter; m++) { + dataFiltered[n + m - c * outputDataLength] = matMul.tensor.data[n + m]; + } + } + } + + this.output.replaceTensorData(dataFiltered); + } + + _createOutputReshapeIndexMap() { + if (this.reshapeIndexMap) { + return; + } + + const nbFilter = this.kernelShape[0]; + const reshape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]]; + const reshapeRowIndices = new _Tensor.default([], reshape, { + type: Int32Array + }); + const reshapeColIndices = new _Tensor.default([], reshape, { + type: Int32Array + }); + this.reshapeIndexMap = new _Tensor.default([], reshape, { + type: Int32Array + }); + + for (let j = 0; j < reshape[1]; j++) { + for (let i = 0; i < reshape[0]; i++) { + _ndarrayOps.default.assigns(reshapeRowIndices.tensor.pick(i, j), i + Math.floor(j / nbFilter) * reshape[0]); + } + } + + for (let j = 0; j < reshape[1]; j++) { + _ndarrayOps.default.assigns(reshapeColIndices.tensor.pick(null, j), j); + } + + _ndarrayOps.default.muls(this.reshapeIndexMap.tensor, reshapeRowIndices.tensor, reshape[1]); + + _ndarrayOps.default.addeq(this.reshapeIndexMap.tensor, reshapeColIndices.tensor); + + this.reshapeIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + super._callGPU(x); + + this._createOutputReshapeIndexMap(); + + if (!this.outputReshaped) { + const reshape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]]; + this.outputReshaped = new _Tensor.default([], reshape); + this.outputReshaped.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputReshaped.is2DReshaped = true; + this.outputReshaped.originalShape = this.outputShape; + this.outputReshaped.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (this.output.glTextureFragments) { + this.output.convert2DRowFragmentedGLTextureToColStack(); + } + + _WebGL.webgl2.runProgram({ + program: this.output.glTextureFragments ? this.mapInputFragmentsProgram : this.mapInputProgram, + output: this.outputReshaped, + inputs: [{ + input: this.output, + name: 'x' + }, { + input: this.reshapeIndexMap, + name: 'indexMap' + }], + uniforms: [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'inputCols' + }], + supportsTextureFragments: true + }); + + if (this.output.glTextureFragments) { + this.output.removeGLTextureFragmentsAsColStack(); + } + } + +} + +class SeparableConv2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'SeparableConv2D'; + const { + filters = 1, + kernel_size = [1, 1], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + depth_multiplier = 1, + activation = 'linear', + use_bias = true + } = attrs; + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size]; + } else { + this.kernelShape = [filters, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else { + this.strides = [strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format; + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + this.activation = activation; + this.activationFunc = activations[activation]; + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + this.useBias = use_bias; + this.params = this.useBias ? ['depthwise_kernel', 'pointwise_kernel', 'bias'] : ['depthwise_kernel', 'pointwise_kernel']; + this.depthwiseConvAttrs = { + filters: depth_multiplier, + kernel_size: [this.kernelShape[1], this.kernelShape[2]], + strides: this.strides, + padding, + data_format, + activation: 'linear', + use_bias: false, + gpu: attrs.gpu + }; + this.pointwiseConvAttrs = { + filters, + kernel_size: [1, 1], + strides: [1, 1], + padding, + data_format, + activation: 'linear', + use_bias, + gpu: attrs.gpu + }; + + if (this.gpu) { + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + setWeights(weightsArr) { + this._depthwiseConv = new _DepthwiseConv2D(this.depthwiseConvAttrs); + + this._depthwiseConv.setWeights(weightsArr.slice(0, 1)); + + this._pointwiseConv = new _Conv2D.default(this.pointwiseConvAttrs); + + this._pointwiseConv.setWeights(weightsArr.slice(1, 3)); + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this._depthwiseConv._callCPU(x); + + this._pointwiseConv._callCPU(this._depthwiseConv.output); + + this.output = this._pointwiseConv.output; + this.activationFunc(this.output); + } + + _callGPU(x) { + this._depthwiseConv.outbound = [null]; + this._pointwiseConv.outbound = [null]; + + this._depthwiseConv._callGPU(x); + + this._pointwiseConv._callGPU(this._depthwiseConv.outputReshaped); + + if (this.activation === 'linear') { + this.output = this._pointwiseConv.output; + } else { + if (!this.output) { + this.output = new _Tensor.default([], this._pointwiseConv.output.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this._pointwiseConv.output.originalShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this._pointwiseConv.output.originalShape, false, -1); + } + + this.outputPreactiv = this._pointwiseConv.output; + + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + +} + +exports.default = SeparableConv2D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/UpSampling1D.js b/keras-js/lib/layers/convolutional/UpSampling1D.js new file mode 100644 index 0000000000..eda598eebf --- /dev/null +++ b/keras-js/lib/layers/convolutional/UpSampling1D.js @@ -0,0 +1,140 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class UpSampling1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'UpSampling1D'; + const { + size = 2 + } = attrs; + this.size = size; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] * this.size, this.inputShape[1]]; + this.output = new _Tensor.default([], this.outputShape); + + for (let i = 0; i < this.size; i++) { + _ndarrayOps.default.assign(this.output.tensor.lo(i, 0).step(this.size, 1), x.tensor); + } + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(null, j), j); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.size; i++) { + _ndarrayOps.default.assign(this.indexMap.tensor.lo(i, 0).step(this.size, 1), indices.tensor); + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] * this.size, this.inputShape[1]]; + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = UpSampling1D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/UpSampling2D.js b/keras-js/lib/layers/convolutional/UpSampling2D.js new file mode 100644 index 0000000000..bd032d24a8 --- /dev/null +++ b/keras-js/lib/layers/convolutional/UpSampling2D.js @@ -0,0 +1,149 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class UpSampling2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'UpSampling2D'; + const { + size = [2, 2], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(size)) { + this.size = size; + } else { + this.size = [size, size]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2]]; + this.output = new _Tensor.default([], this.outputShape); + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + _ndarrayOps.default.assign(this.output.tensor.lo(i, j, 0).step(this.size[0], this.size[1], 1), x.tensor); + } + } + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1); + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + const sliceStart = this.dataFormat === 'channels_first' ? [0, i, j] : [i, j, 0]; + const step = this.dataFormat === 'channels_first' ? [1, this.size[0], this.size[1]] : [this.size[0], this.size[1], 1]; + + _ndarrayOps.default.assign(this.indexMap.tensor.lo(...sliceStart).step(...step), indices.tensor); + } + } + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] * this.size[0], this.inputShape[2] * this.size[1]] : [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = UpSampling2D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/UpSampling3D.js b/keras-js/lib/layers/convolutional/UpSampling3D.js new file mode 100644 index 0000000000..9ea2cd274e --- /dev/null +++ b/keras-js/lib/layers/convolutional/UpSampling3D.js @@ -0,0 +1,153 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class UpSampling3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'UpSampling3D'; + const { + size = [2, 2, 2], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(size)) { + this.size = size; + } else { + this.size = [size, size, size]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2] * this.size[2], this.inputShape[3]]; + this.output = new _Tensor.default([], this.outputShape); + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + for (let k = 0; k < this.size[2]; k++) { + _ndarrayOps.default.assign(this.output.tensor.lo(i, j, k, 0).step(this.size[0], this.size[1], this.size[2], 1), x.tensor); + } + } + } + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2); + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + for (let k = 0; k < this.size[2]; k++) { + const sliceStart = this.dataFormat === 'channels_first' ? [0, i, j, k] : [i, j, k, 0]; + const step = this.dataFormat === 'channels_first' ? [1, this.size[0], this.size[1], this.size[2]] : [this.size[0], this.size[1], this.size[2], 1]; + + _ndarrayOps.default.assign(this.indexMap.tensor.lo(...sliceStart).step(...step), indices.tensor); + } + } + } + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] * this.size[0], this.inputShape[2] * this.size[1], this.inputShape[3] * this.size[2]] : [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2] * this.size[2], this.inputShape[3]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = UpSampling3D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/ZeroPadding1D.js b/keras-js/lib/layers/convolutional/ZeroPadding1D.js new file mode 100644 index 0000000000..62c841cce0 --- /dev/null +++ b/keras-js/lib/layers/convolutional/ZeroPadding1D.js @@ -0,0 +1,145 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class ZeroPadding1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'ZeroPadding1D'; + const { + padding = [1, 1] + } = attrs; + + if (Array.isArray(padding)) { + this.padding = padding; + } else { + this.padding = [padding, padding]; + } + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] + this.padding[0] + this.padding[1], this.inputShape[1]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor.hi(this.inputShape[0] + this.padding[0], this.inputShape[1]).lo(this.padding[0], 0), x.tensor); + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(null, j), j); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = [this.padding[0], 0]; + const sliceEnd = [this.inputShape[0] + this.padding[0], this.inputShape[1]]; + + _ndarrayOps.default.assigns(this.indexMap.tensor, -1); + + _ndarrayOps.default.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor); + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] + this.padding[0] + this.padding[1], this.inputShape[1]]; + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = ZeroPadding1D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/ZeroPadding2D.js b/keras-js/lib/layers/convolutional/ZeroPadding2D.js new file mode 100644 index 0000000000..077f541a13 --- /dev/null +++ b/keras-js/lib/layers/convolutional/ZeroPadding2D.js @@ -0,0 +1,146 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class ZeroPadding2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'ZeroPadding2D'; + const { + padding = [[1, 1], [1, 1]], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(padding)) { + if (Array.isArray(padding[0])) { + this.padding = padding; + } else { + this.padding = [[padding[0], padding[0]], [padding[1], padding[1]]]; + } + } else { + this.padding = [[padding, padding], [padding, padding]]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] + this.padding[0][0] + this.padding[0][1], this.inputShape[1] + this.padding[1][0] + this.padding[1][1], this.inputShape[2]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor.hi(this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2]).lo(this.padding[0][0], this.padding[1][0], 0), x.tensor); + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1); + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = this.dataFormat === 'channels_first' ? [0, this.padding[0][0], this.padding[1][0]] : [this.padding[0][0], this.padding[1][0], 0]; + const sliceEnd = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0], this.inputShape[2] + this.padding[1][0]] : [this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2]]; + + _ndarrayOps.default.assigns(this.indexMap.tensor, -1); + + _ndarrayOps.default.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor); + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0] + this.padding[0][1], this.inputShape[2] + this.padding[1][0] + this.padding[1][1]] : [this.inputShape[0] + this.padding[0][0] + this.padding[0][1], this.inputShape[1] + this.padding[1][0] + this.padding[1][1], this.inputShape[2]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = ZeroPadding2D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/ZeroPadding3D.js b/keras-js/lib/layers/convolutional/ZeroPadding3D.js new file mode 100644 index 0000000000..69917c9e9b --- /dev/null +++ b/keras-js/lib/layers/convolutional/ZeroPadding3D.js @@ -0,0 +1,146 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class ZeroPadding3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'ZeroPadding3D'; + const { + padding = [[1, 1], [1, 1], [1, 1]], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(padding)) { + if (Array.isArray(padding[0])) { + this.padding = padding; + } else { + this.padding = [[padding[0], padding[0]], [padding[1], padding[1]], [padding[2], padding[2]]]; + } + } else { + this.padding = [[padding, padding], [padding, padding], [padding, padding]]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] + this.padding[0][0] + this.padding[0][1], this.inputShape[1] + this.padding[1][0] + this.padding[1][1], this.inputShape[2] + this.padding[2][0] + this.padding[2][1], this.inputShape[3]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor.hi(this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2] + this.padding[2][0], this.inputShape[3]).lo(this.padding[0][0], this.padding[1][0], this.padding[2][0], 0), x.tensor); + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2); + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = this.dataFormat === 'channels_first' ? [0, this.padding[0][0], this.padding[1][0], this.padding[2][0]] : [this.padding[0][0], this.padding[1][0], this.padding[2][0], 0]; + const sliceEnd = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0], this.inputShape[2] + this.padding[1][0], this.inputShape[3] + this.padding[2][0]] : [this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2] + this.padding[2][0], this.inputShape[3]]; + + _ndarrayOps.default.assigns(this.indexMap.tensor, -1); + + _ndarrayOps.default.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor); + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0] + this.padding[0][1], this.inputShape[2] + this.padding[1][0] + this.padding[1][1], this.inputShape[3] + this.padding[2][0] + this.padding[2][1]] : [this.inputShape[0] + this.padding[0][0] + this.padding[0][1], this.inputShape[1] + this.padding[1][0] + this.padding[1][1], this.inputShape[2] + this.padding[2][0] + this.padding[2][1], this.inputShape[3]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = ZeroPadding3D; \ No newline at end of file diff --git a/keras-js/lib/layers/convolutional/index.js b/keras-js/lib/layers/convolutional/index.js new file mode 100644 index 0000000000..ddb1105c55 --- /dev/null +++ b/keras-js/lib/layers/convolutional/index.js @@ -0,0 +1,119 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Conv1D", { + enumerable: true, + get: function () { + return _Conv1D.default; + } +}); +Object.defineProperty(exports, "Conv2D", { + enumerable: true, + get: function () { + return _Conv2D.default; + } +}); +Object.defineProperty(exports, "SeparableConv2D", { + enumerable: true, + get: function () { + return _SeparableConv2D.default; + } +}); +Object.defineProperty(exports, "Conv2DTranspose", { + enumerable: true, + get: function () { + return _Conv2DTranspose.default; + } +}); +Object.defineProperty(exports, "Conv3D", { + enumerable: true, + get: function () { + return _Conv3D.default; + } +}); +Object.defineProperty(exports, "Cropping1D", { + enumerable: true, + get: function () { + return _Cropping1D.default; + } +}); +Object.defineProperty(exports, "Cropping2D", { + enumerable: true, + get: function () { + return _Cropping2D.default; + } +}); +Object.defineProperty(exports, "Cropping3D", { + enumerable: true, + get: function () { + return _Cropping3D.default; + } +}); +Object.defineProperty(exports, "UpSampling1D", { + enumerable: true, + get: function () { + return _UpSampling1D.default; + } +}); +Object.defineProperty(exports, "UpSampling2D", { + enumerable: true, + get: function () { + return _UpSampling2D.default; + } +}); +Object.defineProperty(exports, "UpSampling3D", { + enumerable: true, + get: function () { + return _UpSampling3D.default; + } +}); +Object.defineProperty(exports, "ZeroPadding1D", { + enumerable: true, + get: function () { + return _ZeroPadding1D.default; + } +}); +Object.defineProperty(exports, "ZeroPadding2D", { + enumerable: true, + get: function () { + return _ZeroPadding2D.default; + } +}); +Object.defineProperty(exports, "ZeroPadding3D", { + enumerable: true, + get: function () { + return _ZeroPadding3D.default; + } +}); + +var _Conv1D = _interopRequireDefault(require("./Conv1D")); + +var _Conv2D = _interopRequireDefault(require("./Conv2D")); + +var _SeparableConv2D = _interopRequireDefault(require("./SeparableConv2D")); + +var _Conv2DTranspose = _interopRequireDefault(require("./Conv2DTranspose")); + +var _Conv3D = _interopRequireDefault(require("./Conv3D")); + +var _Cropping1D = _interopRequireDefault(require("./Cropping1D")); + +var _Cropping2D = _interopRequireDefault(require("./Cropping2D")); + +var _Cropping3D = _interopRequireDefault(require("./Cropping3D")); + +var _UpSampling1D = _interopRequireDefault(require("./UpSampling1D")); + +var _UpSampling2D = _interopRequireDefault(require("./UpSampling2D")); + +var _UpSampling3D = _interopRequireDefault(require("./UpSampling3D")); + +var _ZeroPadding1D = _interopRequireDefault(require("./ZeroPadding1D")); + +var _ZeroPadding2D = _interopRequireDefault(require("./ZeroPadding2D")); + +var _ZeroPadding3D = _interopRequireDefault(require("./ZeroPadding3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/core/Activation.js b/keras-js/lib/layers/core/Activation.js new file mode 100644 index 0000000000..ff8c191de5 --- /dev/null +++ b/keras-js/lib/layers/core/Activation.js @@ -0,0 +1,111 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var activations = _interopRequireWildcard(require("../../activations")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Activation extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Activation'; + const { + activation = 'linear' + } = attrs; + this.activation = activation; + this.activationFunc = activations[activation]; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + call(x) { + if (this.activation === 'linear') { + this.output = x; + return this.output; + } + + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = new _Tensor.default(new x.arrayType(x.tensor.data), x.tensor.shape); + this.activationFunc(this.output); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = Activation; \ No newline at end of file diff --git a/keras-js/lib/layers/core/Dense.js b/keras-js/lib/layers/core/Dense.js new file mode 100644 index 0000000000..b1bd4b3f1b --- /dev/null +++ b/keras-js/lib/layers/core/Dense.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class Dense extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Dense'; + const { + units = 1, + activation = 'linear', + input_dim = null, + use_bias = true + } = attrs; + this.activation = activation; + this.activationFunc = activations[this.activation]; + this.units = units; + this.input_dim = input_dim; + this.use_bias = use_bias; + this.params = this.use_bias ? ['kernel', 'bias'] : ['kernel']; + + if (this.input_dim) { + this.inputShape = [this.input_dim]; + } + + if (this.gpu) { + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = new _Tensor.default([], [this.units]); + + if (this.use_bias) { + _ndarrayOps.default.assign(this.output.tensor, this.weights['bias'].tensor); + } + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['kernel'].tensor.transpose(1, 0), x.tensor, 1, this.output.tensor); + this.activationFunc(this.output); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new _Tensor.default([], [this.units]); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [this.units]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const matMulInputs = [{ + input: x, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }]; + + if (this.use_bias) { + matMulInputs.push({ + input: this.weights['bias'], + name: 'C' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ + value: this.use_bias ? 1 : 0, + type: 'bool', + name: 'addC' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }] + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Dense; \ No newline at end of file diff --git a/keras-js/lib/layers/core/Dropout.js b/keras-js/lib/layers/core/Dropout.js new file mode 100644 index 0000000000..60e9b0c37d --- /dev/null +++ b/keras-js/lib/layers/core/Dropout.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Dropout extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Dropout'; + const { + rate = 0.5 + } = attrs; + this.rate = Math.min(Math.max(0, rate), 1); + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = Dropout; \ No newline at end of file diff --git a/keras-js/lib/layers/core/Flatten.js b/keras-js/lib/layers/core/Flatten.js new file mode 100644 index 0000000000..df0e85f85b --- /dev/null +++ b/keras-js/lib/layers/core/Flatten.js @@ -0,0 +1,128 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const flattenProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int outputSize;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(outputSize) * outTex.x);\r\n int out_y = 0;\r\n\r\n int i = int(floor(float(out_x) / float(inputCols)));\r\n int j = int(mod(float(out_x), float(inputCols)));\r\n outColor = vec4(texelFetch(x, ivec2(j, i), 0).r);\r\n}\r\n"; +const flattenFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int outputSize;\r\nuniform int inputRows;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(outputSize) * outTex.x);\r\n int out_y = 0;\r\n\r\n int rowIndex = int(mod(floor(float(out_x) / float(inputCols)), float(inputRows)));\r\n int colIndex = int(mod(float(out_x), float(inputCols)));\r\n int fragmentIndex = int(floor(float(out_x) / (float(inputRows) * float(inputCols))));\r\n colIndex += fragmentIndex * inputCols;\r\n outColor = vec4(texelFetch(x, ivec2(colIndex, rowIndex), 0).r);\r\n}\r\n"; + +class Flatten extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Flatten'; + + if (this.gpu) { + this.flattenProgram = _WebGL.webgl2.compileProgram(flattenProgramSource); + this.flattenFragmentsProgram = _WebGL.webgl2.compileProgram(flattenFragmentsProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (x.tensor.shape.length <= 1) { + this.output = x; + } else { + this.output = new _Tensor.default([], [x.tensor.shape.reduce((a, b) => a * b, 1)]); + this.output.replaceTensorData(x.tensor.data); + } + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + + if (!this.output) { + this.output = new _Tensor.default([], [x.glTextureShape.reduce((a, b) => a * b, 1)]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (x.glTextureFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + + _WebGL.webgl2.runProgram({ + program: this.flattenFragmentsProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'outputSize' + }, { + value: x.glTextureShape[0], + type: 'int', + name: 'inputRows' + }, { + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }], + supportsTextureFragments: true + }); + + x.removeGLTextureFragmentsAsColStack(); + } else { + _WebGL.webgl2.runProgram({ + program: this.flattenProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'outputSize' + }, { + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Flatten; \ No newline at end of file diff --git a/keras-js/lib/layers/core/Permute.js b/keras-js/lib/layers/core/Permute.js new file mode 100644 index 0000000000..cafda5e68a --- /dev/null +++ b/keras-js/lib/layers/core/Permute.js @@ -0,0 +1,194 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _last2 = _interopRequireDefault(require("lodash/last")); + +var _range2 = _interopRequireDefault(require("lodash/range")); + +var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Permute extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Permute'; + const { + dims = [] + } = attrs; + this.dims = dims.map(dim => dim - 1); + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (x.tensor.shape.length <= 1 || (0, _isEqual2.default)((0, _range2.default)(x.tensor.shape.length), this.dims)) { + this.output = x; + return this.output; + } + + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dims.length !== x.tensor.shape.length) { + this.throwError('The specified dims permutation must match the number of dimensions.'); + } + + const outputShape = this.dims.map(i => x.tensor.shape[i]); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.assign(this.output.tensor, x.tensor.transpose(...this.dims)); + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + if (this.inputShape.length === 2) { + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + } else if (this.inputShape.length === 3) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, j, null), i * this.inputShape[1] + j); + } + } + } else if (this.inputShape.length === 4) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + for (let k = 0; k < this.inputShape[2]; k++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, j, k, null), i * this.inputShape[1] * this.inputShape[2] + j * this.inputShape[2] + k); + } + } + } + } + + for (let c = 0; c < (0, _last2.default)(this.inputShape); c++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(...Array(this.inputShape.length - 1).fill(null), c), c); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, (0, _last2.default)(this.inputShape)); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + const outputShape = this.dims.map(i => this.inputShape[i]); + this.indexMap = new _Tensor.default([], outputShape, { + type: Int32Array + }); + + _ndarrayOps.default.assign(this.indexMap.tensor, indices.tensor.transpose(...this.dims)); + + if (outputShape.length > 2) { + this.indexMap.reshapeTo2D(); + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + this.inputShape = x.tensor.shape; + + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + + this._createIndexMap(); + + if (!this.output) { + const outputShape = this.dims.map(i => this.inputShape[i]); + this.output = new _Tensor.default([], outputShape); + + if (outputShape.length > 2) { + this.output.reshapeTo2D(); + } + + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = Permute; \ No newline at end of file diff --git a/keras-js/lib/layers/core/RepeatVector.js b/keras-js/lib/layers/core/RepeatVector.js new file mode 100644 index 0000000000..df1eab5a16 --- /dev/null +++ b/keras-js/lib/layers/core/RepeatVector.js @@ -0,0 +1,87 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayUnsqueeze = _interopRequireDefault(require("ndarray-unsqueeze")); + +var _ndarrayTile = _interopRequireDefault(require("ndarray-tile")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = texture(x, vec2(outTex.x, 0));\r\n}\r\n"; + +class RepeatVector extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'RepeatVector'; + const { + n = 1 + } = attrs; + this.n = n; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (x.tensor.shape.length !== 1) { + this.throwError('Only 1D tensor inputs allowed.'); + } + + this.output = new _Tensor.default([], [this.n, x.tensor.shape[1]]); + this.output.tensor = (0, _ndarrayTile.default)((0, _ndarrayUnsqueeze.default)(x.tensor, 0), [this.n, 1]); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [this.n, x.glTextureShape[1]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = RepeatVector; \ No newline at end of file diff --git a/keras-js/lib/layers/core/Reshape.js b/keras-js/lib/layers/core/Reshape.js new file mode 100644 index 0000000000..c056f7050d --- /dev/null +++ b/keras-js/lib/layers/core/Reshape.js @@ -0,0 +1,180 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _last2 = _interopRequireDefault(require("lodash/last")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Reshape extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Reshape'; + const { + target_shape = [] + } = attrs; + this.targetShape = target_shape; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.targetShape.reduce((a, b) => a * b, 1) !== x.tensor.size) { + this.throwError('The total size of new array must be unchanged in reshape layer.'); + } + + this.output = new _Tensor.default([], this.targetShape); + this.output.replaceTensorData(x.tensor.data); + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + if (this.inputShape.length === 2) { + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + } else if (this.inputShape.length === 3) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, j, null), i * this.inputShape[1] + j); + } + } + } else if (this.inputShape.length === 4) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + for (let k = 0; k < this.inputShape[2]; k++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, j, k, null), i * this.inputShape[1] * this.inputShape[2] + j * this.inputShape[2] + k); + } + } + } + } + + for (let c = 0; c < (0, _last2.default)(this.inputShape); c++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(...Array(this.inputShape.length - 1).fill(null), c), c); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, (0, _last2.default)(this.inputShape)); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + this.indexMap = new _Tensor.default([], this.targetShape, { + type: Int32Array + }); + this.indexMap.replaceTensorData(new Int32Array(indices.tensor.data)); + + if (this.targetShape.length > 2) { + this.indexMap.reshapeTo2D(); + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + this.inputShape = x.tensor.shape; + + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.targetShape); + + if (this.targetShape.length > 2) { + this.output.reshapeTo2D(); + } + + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = Reshape; \ No newline at end of file diff --git a/keras-js/lib/layers/core/SpatialDropout1D.js b/keras-js/lib/layers/core/SpatialDropout1D.js new file mode 100644 index 0000000000..a42b324b4b --- /dev/null +++ b/keras-js/lib/layers/core/SpatialDropout1D.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class SpatialDropout1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'SpatialDropout1D'; + const { + p = 0.5 + } = attrs; + this.p = Math.min(Math.max(0, p), 1); + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = SpatialDropout1D; \ No newline at end of file diff --git a/keras-js/lib/layers/core/SpatialDropout2D.js b/keras-js/lib/layers/core/SpatialDropout2D.js new file mode 100644 index 0000000000..38949bd9f7 --- /dev/null +++ b/keras-js/lib/layers/core/SpatialDropout2D.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class SpatialDropout2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'SpatialDropout2D'; + const { + rate = 0.5, + data_format = 'channels_last' + } = attrs; + this.rate = Math.min(Math.max(0, rate), 1); + this.dataFormat = data_format; + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = SpatialDropout2D; \ No newline at end of file diff --git a/keras-js/lib/layers/core/SpatialDropout3D.js b/keras-js/lib/layers/core/SpatialDropout3D.js new file mode 100644 index 0000000000..abbe65a7ff --- /dev/null +++ b/keras-js/lib/layers/core/SpatialDropout3D.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class SpatialDropout3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'SpatialDropout3D'; + const { + rate = 0.5, + data_format = 'channels_last' + } = attrs; + this.rate = Math.min(Math.max(0, rate), 1); + this.dataFormat = data_format; + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = SpatialDropout3D; \ No newline at end of file diff --git a/keras-js/lib/layers/core/index.js b/keras-js/lib/layers/core/index.js new file mode 100644 index 0000000000..9a078e0b87 --- /dev/null +++ b/keras-js/lib/layers/core/index.js @@ -0,0 +1,87 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Dense", { + enumerable: true, + get: function () { + return _Dense.default; + } +}); +Object.defineProperty(exports, "Activation", { + enumerable: true, + get: function () { + return _Activation.default; + } +}); +Object.defineProperty(exports, "Dropout", { + enumerable: true, + get: function () { + return _Dropout.default; + } +}); +Object.defineProperty(exports, "SpatialDropout1D", { + enumerable: true, + get: function () { + return _SpatialDropout1D.default; + } +}); +Object.defineProperty(exports, "SpatialDropout2D", { + enumerable: true, + get: function () { + return _SpatialDropout2D.default; + } +}); +Object.defineProperty(exports, "SpatialDropout3D", { + enumerable: true, + get: function () { + return _SpatialDropout3D.default; + } +}); +Object.defineProperty(exports, "Flatten", { + enumerable: true, + get: function () { + return _Flatten.default; + } +}); +Object.defineProperty(exports, "Reshape", { + enumerable: true, + get: function () { + return _Reshape.default; + } +}); +Object.defineProperty(exports, "Permute", { + enumerable: true, + get: function () { + return _Permute.default; + } +}); +Object.defineProperty(exports, "RepeatVector", { + enumerable: true, + get: function () { + return _RepeatVector.default; + } +}); + +var _Dense = _interopRequireDefault(require("./Dense")); + +var _Activation = _interopRequireDefault(require("./Activation")); + +var _Dropout = _interopRequireDefault(require("./Dropout")); + +var _SpatialDropout1D = _interopRequireDefault(require("./SpatialDropout1D")); + +var _SpatialDropout2D = _interopRequireDefault(require("./SpatialDropout2D")); + +var _SpatialDropout3D = _interopRequireDefault(require("./SpatialDropout3D")); + +var _Flatten = _interopRequireDefault(require("./Flatten")); + +var _Reshape = _interopRequireDefault(require("./Reshape")); + +var _Permute = _interopRequireDefault(require("./Permute")); + +var _RepeatVector = _interopRequireDefault(require("./RepeatVector")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/embeddings/Embedding.js b/keras-js/lib/layers/embeddings/Embedding.js new file mode 100644 index 0000000000..0011414a94 --- /dev/null +++ b/keras-js/lib/layers/embeddings/Embedding.js @@ -0,0 +1,94 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D embeddings;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 x_size = textureSize(x, 0);\r\n ivec2 embeddings_size = textureSize(embeddings, 0);\r\n int out_x = int(float(embeddings_size[0]) * outTex.x);\r\n int out_y = int(float(x_size[0]) * outTex.y);\r\n\r\n int index = int(texelFetch(x, ivec2(out_y, 0), 0).r);\r\n outColor = texelFetch(embeddings, ivec2(out_x, index), 0);\r\n}\r\n"; + +class Embedding extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Embedding'; + const { + input_dim = 1, + output_dim = 1, + input_length = 0, + mask_zero = false + } = attrs; + this.inputDim = input_dim; + this.outputDim = output_dim; + this.inputLength = input_length; + this.maskZero = mask_zero; + this.params = ['embeddings']; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = new _Tensor.default([], [x.tensor.shape[0], this.weights['embeddings'].tensor.shape[1]]); + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + _ndarrayOps.default.assign(this.output.tensor.pick(i, null), this.weights['embeddings'].tensor.pick(x.tensor.get(i), null)); + } + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [x.glTextureShape[1], this.weights['embeddings'].glTextureShape[1]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.weights['embeddings'], + name: 'embeddings' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Embedding; \ No newline at end of file diff --git a/keras-js/lib/layers/embeddings/index.js b/keras-js/lib/layers/embeddings/index.js new file mode 100644 index 0000000000..68fc079719 --- /dev/null +++ b/keras-js/lib/layers/embeddings/index.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Embedding", { + enumerable: true, + get: function () { + return _Embedding.default; + } +}); + +var _Embedding = _interopRequireDefault(require("./Embedding")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/index.js b/keras-js/lib/layers/index.js new file mode 100644 index 0000000000..218f1c290e --- /dev/null +++ b/keras-js/lib/layers/index.js @@ -0,0 +1,148 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var _exportNames = { + InputLayer: true +}; +Object.defineProperty(exports, "InputLayer", { + enumerable: true, + get: function () { + return _InputLayer.default; + } +}); + +var _InputLayer = _interopRequireDefault(require("./InputLayer")); + +var _advanced_activations = require("./advanced_activations"); + +Object.keys(_advanced_activations).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _advanced_activations[key]; + } + }); +}); + +var _convolutional = require("./convolutional"); + +Object.keys(_convolutional).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _convolutional[key]; + } + }); +}); + +var _core = require("./core"); + +Object.keys(_core).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _core[key]; + } + }); +}); + +var _embeddings = require("./embeddings"); + +Object.keys(_embeddings).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _embeddings[key]; + } + }); +}); + +var _merge = require("./merge"); + +Object.keys(_merge).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _merge[key]; + } + }); +}); + +var _noise = require("./noise"); + +Object.keys(_noise).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _noise[key]; + } + }); +}); + +var _normalization = require("./normalization"); + +Object.keys(_normalization).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _normalization[key]; + } + }); +}); + +var _pooling = require("./pooling"); + +Object.keys(_pooling).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _pooling[key]; + } + }); +}); + +var _recurrent = require("./recurrent"); + +Object.keys(_recurrent).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _recurrent[key]; + } + }); +}); + +var _wrappers = require("./wrappers"); + +Object.keys(_wrappers).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _wrappers[key]; + } + }); +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/merge/Add.js b/keras-js/lib/layers/merge/Add.js new file mode 100644 index 0000000000..1cbd95c0c4 --- /dev/null +++ b/keras-js/lib/layers/merge/Add.js @@ -0,0 +1,48 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Add extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Add'; + this.mode = 'sum'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + for (let i = 0; i < inputs.length; i++) { + _ndarrayOps.default.addeq(this.output.tensor, inputs[i].tensor); + } + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('add', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Add; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/Average.js b/keras-js/lib/layers/merge/Average.js new file mode 100644 index 0000000000..7386a75bdb --- /dev/null +++ b/keras-js/lib/layers/merge/Average.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Average extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Average'; + this.mode = 'ave'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + for (let i = 0; i < inputs.length; i++) { + _ndarrayOps.default.addeq(this.output.tensor, inputs[i].tensor); + } + + _ndarrayOps.default.divseq(this.output.tensor, inputs.length); + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('average', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Average; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/Concatenate.js b/keras-js/lib/layers/merge/Concatenate.js new file mode 100644 index 0000000000..1ae70447b6 --- /dev/null +++ b/keras-js/lib/layers/merge/Concatenate.js @@ -0,0 +1,143 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _sum2 = _interopRequireDefault(require("lodash/sum")); + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayConcatRows = _interopRequireDefault(require("ndarray-concat-rows")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Concatenate extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Concatenate'; + this.mode = 'concat'; + const { + axis = -1 + } = attrs; + this.concatAxis = axis <= 0 ? axis : axis - 1; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + + const _concatAxis = this.concatAxis < 0 ? outputShape.length + this.concatAxis : this.concatAxis; + + inputs.slice(1, inputs.length).forEach(x => { + const d = x.tensor.shape.slice()[_concatAxis]; + + outputShape[_concatAxis] += d; + }); + this.output = new _Tensor.default([], outputShape); + + if (_concatAxis === 0) { + (0, _ndarrayConcatRows.default)(this.output.tensor, inputs.map(x => x.tensor)); + } else { + let dimsAxisSwap = [_concatAxis]; + + for (let i = 0; i < inputs[0].tensor.shape.length; i++) { + if (i !== _concatAxis) dimsAxisSwap.push(i); + } + + (0, _ndarrayConcatRows.default)(this.output.tensor.transpose(...dimsAxisSwap), inputs.map(x => x.tensor.transpose(...dimsAxisSwap))); + } + } + + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + }); + const outputShape = inputs[0].glTextureShape.slice(); + let _concatAxis = 1; + + if (inputs[0].is2DReshaped) { + if (this.concatAxis === -1 || this.concatAxis === inputs[0].originalShape.length - 1) { + _concatAxis = 1; + } else { + this.throwError('specified axis not supported for now.'); + } + } else { + if (this.concatAxis === -1 || this.concatAxis === 1) { + _concatAxis = 1; + } else if (this.concatAxis === -2 || this.concatAxis === 0) { + _concatAxis = 0; + } else { + this.throwError('specified axis not supported for now.'); + } + } + + outputShape[_concatAxis] = (0, _sum2.default)(inputs.map(input => input.glTextureShape[_concatAxis])); + + if (!this.output) { + this.output = new _Tensor.default([], outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: _concatAxis === 1 + }); + + if (inputs[0].is1D) { + this.output.is1D = inputs[0].is1D; + } else if (inputs[0].is2DReshaped) { + this.output.is2DReshaped = inputs[0].is2DReshaped; + this.output.originalShape = inputs[0].originalShape.slice(); + + const _concatAxis = this.concatAxis < 0 ? this.output.originalShape.length + this.concatAxis : this.concatAxis; + + this.output.originalShape[_concatAxis] = (0, _sum2.default)(inputs.map(input => input.originalShape[_concatAxis])); + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.output.originalShape, false, _concatAxis); + } + } + + if (!this.mergeProgram) { + const outputShape = this.output.glTextureFragments ? this.output.glTextureFragmentShape : this.output.glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('concatenate', inputs.length, inputs.map(input => input.glTextureShape), outputShape, _concatAxis); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + _WebGL.webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: inputs.map((input, i) => ({ + input, + name: `inputs[${i}]` + })), + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = Concatenate; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/Dot.js b/keras-js/lib/layers/merge/Dot.js new file mode 100644 index 0000000000..b0c09931b9 --- /dev/null +++ b/keras-js/lib/layers/merge/Dot.js @@ -0,0 +1,159 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D input1;\r\nuniform sampler2D input2;\r\nuniform int rows;\r\nuniform int cols;\r\nuniform int dotAxis1;\r\nuniform int dotAxis2;\r\nuniform int commonDim;\r\nuniform bool normalize;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(cols) * outTex.x);\r\n int out_y = int(float(rows) * outTex.y);\r\n\r\n float sum = 0.;\r\n float a = 0.;\r\n float b = 0.;\r\n float norm1 = 0.;\r\n float norm2 = 0.;\r\n\r\n for (int i = 0; i < commonDim; ++i) {\r\n if (dotAxis1 == 0 && dotAxis2 == 0) {\r\n a = texelFetch(input1, ivec2(out_y, i), 0).r;\r\n b = texelFetch(input2, ivec2(out_x, i), 0).r;\r\n } else if (dotAxis1 == 1 && dotAxis2 == 1) {\r\n a = texelFetch(input1, ivec2(i, out_y), 0).r;\r\n b = texelFetch(input2, ivec2(i, out_x), 0).r;\r\n }\r\n\r\n sum += a * b;\r\n\r\n if (normalize) {\r\n norm1 += a * a;\r\n norm2 += b * b;\r\n }\r\n }\r\n\r\n if (normalize) {\r\n sum /= sqrt(norm1) * sqrt(norm2);\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class Dot extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Dot'; + this.mode = 'dot'; + const { + axes = -1, + normalize = false + } = attrs; + + if (Array.isArray(axes)) { + this.dotAxes = [axes[0] <= 0 ? axes[0] : axes[0] - 1, axes[1] <= 0 ? axes[1] : axes[1] - 1]; + } else { + this.dotAxes = [axes <= 0 ? axes : axes - 1, axes <= 0 ? axes : axes - 1]; + } + + this.normalize = normalize; + + if (this.gpu) { + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + } + + _calcOutputShape(inputShapes) { + let shape1 = inputShapes[0].slice(); + let shape2 = inputShapes[1].slice(); + shape1.splice(this.dotAxes[0], 1); + shape2.splice(this.dotAxes[1], 1); + this.outputShape = shape1.concat(shape2); + + if (this.outputShape.length === 1) { + this.outputShape.push(1); + } + } + + _callCPU(inputs) { + this._calcOutputShape([inputs[0].tensor.shape, inputs[1].tensor.shape]); + + this.output = new _Tensor.default([], this.outputShape); + + if (inputs[0].tensor.shape.length === 2 && inputs[1].tensor.shape.length === 2) { + if (this.dotAxes[0] === 0 && this.dotAxes[1] === 0) { + if (this.normalize) { + for (let i = 0; i < inputs[0].tensor.shape[1]; i++) { + _ndarrayOps.default.divseq(inputs[0].tensor.pick(null, i), _ndarrayOps.default.norm2(inputs[0].tensor.pick(null, i))); + } + + for (let i = 0; i < inputs[1].tensor.shape[1]; i++) { + _ndarrayOps.default.divseq(inputs[1].tensor.pick(null, i), _ndarrayOps.default.norm2(inputs[1].tensor.pick(null, i))); + } + } + + (0, _ndarrayGemm.default)(this.output.tensor, inputs[0].tensor.transpose(1, 0), inputs[1].tensor); + } else if (this.dotAxes[0] === 1 && this.dotAxes[1] === 1) { + if (this.normalize) { + for (let i = 0; i < inputs[0].tensor.shape[0]; i++) { + _ndarrayOps.default.divseq(inputs[0].tensor.pick(i, null), _ndarrayOps.default.norm2(inputs[0].tensor.pick(i, null))); + } + + for (let i = 0; i < inputs[1].tensor.shape[0]; i++) { + _ndarrayOps.default.divseq(inputs[1].tensor.pick(i, null), _ndarrayOps.default.norm2(inputs[1].tensor.pick(i, null))); + } + } + + (0, _ndarrayGemm.default)(this.output.tensor, inputs[0].tensor, inputs[1].tensor.transpose(1, 0)); + } + } else { + this.throwError('dot mode for 3+ dim tensors not yet implemented.'); + } + } + + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ + type: '2d', + format: 'float' + }); + } + }); + + this._calcOutputShape([inputs[0].glTextureShape, inputs[1].glTextureShape]); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const commonDim = inputs[0].glTextureShape[this.dotAxes[0]]; + + _WebGL.webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: [{ + input: inputs[0], + name: 'input1' + }, { + input: inputs[1], + name: 'input2' + }], + uniforms: [{ + value: this.output.glTextureShape[0], + type: 'int', + name: 'rows' + }, { + value: this.output.glTextureShape[1], + type: 'int', + name: 'cols' + }, { + value: this.dotAxes[0], + type: 'int', + name: 'dotAxis1' + }, { + value: this.dotAxes[1], + type: 'int', + name: 'dotAxis2' + }, { + value: commonDim, + type: 'int', + name: 'commonDim' + }, { + value: +this.normalize, + type: 'bool', + name: 'normalize' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Dot; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/Maximum.js b/keras-js/lib/layers/merge/Maximum.js new file mode 100644 index 0000000000..a80055bd19 --- /dev/null +++ b/keras-js/lib/layers/merge/Maximum.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Maximum extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Maximum'; + this.mode = 'max'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.assign(this.output.tensor, inputs[0].tensor); + + for (let i = 1; i < inputs.length; i++) { + _ndarrayOps.default.maxeq(this.output.tensor, inputs[i].tensor); + } + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('maximum', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Maximum; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/Minimum.js b/keras-js/lib/layers/merge/Minimum.js new file mode 100644 index 0000000000..f935cc4db5 --- /dev/null +++ b/keras-js/lib/layers/merge/Minimum.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Minimum extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Minimum'; + this.mode = 'min'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.assign(this.output.tensor, inputs[0].tensor); + + for (let i = 1; i < inputs.length; i++) { + _ndarrayOps.default.mineq(this.output.tensor, inputs[i].tensor); + } + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('minimum', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Minimum; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/Multiply.js b/keras-js/lib/layers/merge/Multiply.js new file mode 100644 index 0000000000..bf2a9833fe --- /dev/null +++ b/keras-js/lib/layers/merge/Multiply.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Multiply extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Multiply'; + this.mode = 'mul'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.assigns(this.output.tensor, 1); + + for (let i = 0; i < inputs.length; i++) { + _ndarrayOps.default.muleq(this.output.tensor, inputs[i].tensor); + } + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('multiply', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Multiply; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/Subtract.js b/keras-js/lib/layers/merge/Subtract.js new file mode 100644 index 0000000000..23fe170588 --- /dev/null +++ b/keras-js/lib/layers/merge/Subtract.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Subtract extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Subtract'; + this.mode = 'diff'; + } + + _callCPU(inputs) { + if (inputs.length !== 2) { + this.throwError('Inputs should be an array of 2 Tensors.'); + } + + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.sub(this.output.tensor, inputs[0].tensor, inputs[1].tensor); + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('subtract', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Subtract; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/_Merge.js b/keras-js/lib/layers/merge/_Merge.js new file mode 100644 index 0000000000..79543bc51b --- /dev/null +++ b/keras-js/lib/layers/merge/_Merge.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class _Merge extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_Merge'; + this.isMergeLayer = true; + } + + call(inputs) { + if (this.gpu) { + this._callGPU(inputs); + } else { + const valid = this._validateInputs(inputs); + + if (!valid) { + this.throwError('Invalid inputs to call method.'); + } + + this._callCPU(inputs); + } + + return this.output; + } + + _validateInputs(inputs) { + const shapes = inputs.map(x => x.tensor.shape.slice()); + + if (['sum', 'diff', 'mul', 'ave', 'max', 'min'].indexOf(this.mode) > -1) { + if (!shapes.every(shape => (0, _isEqual2.default)(shape, shapes[0]))) { + this.throwError(`All input shapes must be the same for mode ${this.mode}.`); + } + } + + if (this.mode === 'dot') { + if (inputs.length !== 2) { + this.throwError(`Exactly 2 inputs required for mode ${this.mode}.`); + } + + if (this.dotAxes[0] < 0) { + this.dotAxes[0] = shapes[0].length + this.dotAxes[0]; + } + + if (this.dotAxes[1] < 0) { + this.dotAxes[1] = shapes[1].length + this.dotAxes[1]; + } + + if (shapes[0][this.dotAxes[0]] !== shapes[1][this.dotAxes[1]]) { + this.throwError('Dimensions incompatibility using dot mode.'); + } + } else if (this.mode === 'concat') { + let nonConcatShapes = shapes.slice(); + + let _concatAxis = this.concatAxis < 0 ? nonConcatShapes[0].length + this.concatAxis : this.concatAxis; + + if (this.concatAxis === 0) _concatAxis = 0; + (0, _range2.default)(nonConcatShapes.length).forEach(i => { + nonConcatShapes[i].splice(_concatAxis, 1); + }); + + if (!nonConcatShapes.every(shape => (0, _isEqual2.default)(shape, nonConcatShapes[0]))) { + this.throwError('In concat mode, all shapes must be the same except along the concat axis.'); + } + } + + return true; + } + + _callCPU() {} + + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + }); + + if (!this.output) { + this.output = new _Tensor.default([], inputs[0].glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (inputs[0].is1D) { + this.output.is1D = inputs[0].is1D; + } else if (inputs[0].is2DReshaped || inputs[0].is2DSquareReshaped) { + if (inputs[0].is2DReshaped) { + this.output.is2DReshaped = inputs[0].is2DReshaped; + } else if (inputs[0].is2DSquareReshaped) { + this.output.is2DSquareReshaped = inputs[0].is2DSquareReshaped; + } + + this.output.originalShape = inputs[0].originalShape.slice(); + this.output.indicesForReshaped = inputs[0].indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: inputs.map((input, i) => ({ + input, + name: `inputs[${i}]` + })), + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = _Merge; \ No newline at end of file diff --git a/keras-js/lib/layers/merge/index.js b/keras-js/lib/layers/merge/index.js new file mode 100644 index 0000000000..92e1fc1927 --- /dev/null +++ b/keras-js/lib/layers/merge/index.js @@ -0,0 +1,71 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Add", { + enumerable: true, + get: function () { + return _Add.default; + } +}); +Object.defineProperty(exports, "Subtract", { + enumerable: true, + get: function () { + return _Subtract.default; + } +}); +Object.defineProperty(exports, "Multiply", { + enumerable: true, + get: function () { + return _Multiply.default; + } +}); +Object.defineProperty(exports, "Average", { + enumerable: true, + get: function () { + return _Average.default; + } +}); +Object.defineProperty(exports, "Maximum", { + enumerable: true, + get: function () { + return _Maximum.default; + } +}); +Object.defineProperty(exports, "Minimum", { + enumerable: true, + get: function () { + return _Minimum.default; + } +}); +Object.defineProperty(exports, "Concatenate", { + enumerable: true, + get: function () { + return _Concatenate.default; + } +}); +Object.defineProperty(exports, "Dot", { + enumerable: true, + get: function () { + return _Dot.default; + } +}); + +var _Add = _interopRequireDefault(require("./Add")); + +var _Subtract = _interopRequireDefault(require("./Subtract")); + +var _Multiply = _interopRequireDefault(require("./Multiply")); + +var _Average = _interopRequireDefault(require("./Average")); + +var _Maximum = _interopRequireDefault(require("./Maximum")); + +var _Minimum = _interopRequireDefault(require("./Minimum")); + +var _Concatenate = _interopRequireDefault(require("./Concatenate")); + +var _Dot = _interopRequireDefault(require("./Dot")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/noise/GaussianDropout.js b/keras-js/lib/layers/noise/GaussianDropout.js new file mode 100644 index 0000000000..2eeefe7648 --- /dev/null +++ b/keras-js/lib/layers/noise/GaussianDropout.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GaussianDropout extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GaussianDropout'; + const { + rate = 0.5 + } = attrs; + this.rate = Math.min(Math.max(0, rate), 1); + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = GaussianDropout; \ No newline at end of file diff --git a/keras-js/lib/layers/noise/GaussianNoise.js b/keras-js/lib/layers/noise/GaussianNoise.js new file mode 100644 index 0000000000..d8a7e7de58 --- /dev/null +++ b/keras-js/lib/layers/noise/GaussianNoise.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GaussianNoise extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GaussianNoise'; + const { + stddev = 0 + } = attrs; + this.stddev = stddev; + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = GaussianNoise; \ No newline at end of file diff --git a/keras-js/lib/layers/noise/index.js b/keras-js/lib/layers/noise/index.js new file mode 100644 index 0000000000..74e2a4a66c --- /dev/null +++ b/keras-js/lib/layers/noise/index.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "GaussianDropout", { + enumerable: true, + get: function () { + return _GaussianDropout.default; + } +}); +Object.defineProperty(exports, "GaussianNoise", { + enumerable: true, + get: function () { + return _GaussianNoise.default; + } +}); + +var _GaussianDropout = _interopRequireDefault(require("./GaussianDropout")); + +var _GaussianNoise = _interopRequireDefault(require("./GaussianNoise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/normalization/BatchNormalization.js b/keras-js/lib/layers/normalization/BatchNormalization.js new file mode 100644 index 0000000000..d3d7dffbff --- /dev/null +++ b/keras-js/lib/layers/normalization/BatchNormalization.js @@ -0,0 +1,272 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D X;\r\nuniform isampler2D normAxisIndexMap;\r\nuniform sampler2D gamma;\r\nuniform sampler2D beta;\r\nuniform sampler2D mean;\r\nuniform sampler2D std;\r\nuniform float epsilon;\r\nuniform bool scale;\r\nuniform bool center;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(X, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\nint normAxisIndex = texelFetch(normAxisIndexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n float _x = texelFetch(X, ivec2(out_x, out_y), 0).r;\r\n float _mean = texelFetch(mean, ivec2(normAxisIndex, 0), 0).r;\r\n float _std = texelFetch(std, ivec2(normAxisIndex, 0), 0).r;\r\n\r\n float _gamma = 1.0;\r\n if (scale) {\r\n _gamma = texelFetch(gamma, ivec2(normAxisIndex, 0), 0).r;\r\n }\r\n\r\n float _beta = 0.0;\r\n if (center) {\r\n _beta = texelFetch(beta, ivec2(normAxisIndex, 0), 0).r;\r\n }\r\n\r\n float sum = _beta + _gamma * (_x - _mean) / sqrt(_std + epsilon);\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class BatchNormalization extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'BatchNormalization'; + const { + epsilon = 0.001, + axis = -1, + center = true, + scale = true + } = attrs; + this.epsilon = epsilon; + this.center = center; + this.scale = scale; + this.axis = axis; + this.axisNormalized = false; + this.params = []; + + if (this.scale) { + this.params.push('gamma'); + } + + if (this.center) { + this.params.push('beta'); + } + + this.params = this.params.concat(['moving_mean', 'moving_variance']); + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (!this.axisNormalized) { + this.axis = this.axis < 0 ? x.tensor.shape.length + this.axis : this.axis - 1; + this.axisNormalized = true; + } + + let broadcast = []; + + for (let d = 0; d < x.tensor.shape.length; d++) { + if (d === this.axis) broadcast.push(1);else broadcast.push(null); + } + + let _gamma = new _Tensor.default([], x.tensor.shape); + + let _beta = new _Tensor.default([], x.tensor.shape); + + for (let i = 0; i < x.tensor.shape[this.axis]; i++) { + broadcast[this.axis] = i; + + if (this.scale) { + _ndarrayOps.default.assigns(_gamma.tensor.pick(...broadcast), this.weights['gamma'].tensor.get(i)); + } + + if (this.center) { + _ndarrayOps.default.assigns(_beta.tensor.pick(...broadcast), this.weights['beta'].tensor.get(i)); + } + } + + let _mean = new _Tensor.default([], x.tensor.shape); + + let _std = new _Tensor.default([], x.tensor.shape); + + for (let i = 0; i < x.tensor.shape[this.axis]; i++) { + broadcast[this.axis] = i; + + _ndarrayOps.default.assigns(_mean.tensor.pick(...broadcast), this.weights['moving_mean'].tensor.get(i)); + + _ndarrayOps.default.assigns(_std.tensor.pick(...broadcast), this.weights['moving_variance'].tensor.get(i) + this.epsilon); + } + + _ndarrayOps.default.sqrteq(_std.tensor); + + this.output = new _Tensor.default(x.tensor.data, x.tensor.shape); + + _ndarrayOps.default.subeq(this.output.tensor, _mean.tensor); + + _ndarrayOps.default.diveq(this.output.tensor, _std.tensor); + + if (this.scale) { + _ndarrayOps.default.muleq(this.output.tensor, _gamma.tensor); + } + + if (this.center) { + _ndarrayOps.default.addeq(this.output.tensor, _beta.tensor); + } + } + + _createIndexMap(glTextureShape, indicesForReshaped) { + if (this.normAxisIndexMap) { + return; + } + + const _normAxisIndexMap = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + this.normAxisIndexMap = new _Tensor.default([], glTextureShape, { + type: Int32Array + }); + const slice = Array(this.inputShape.length).fill(null); + + for (let i = 0; i < this.inputShape[this.axis]; i++) { + slice[this.axis] = i; + + _ndarrayOps.default.assigns(_normAxisIndexMap.tensor.pick(...slice), i); + } + + if (indicesForReshaped) { + for (let i = 0; i < indicesForReshaped.data.length; i++) { + this.normAxisIndexMap.tensor.data[indicesForReshaped.data[i]] = _normAxisIndexMap.tensor.data[i]; + } + } else { + this.normAxisIndexMap = _normAxisIndexMap; + } + + this.normAxisIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (!this.axisNormalized) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + + this.axis = this.axis < 0 ? this.inputShape.length + this.axis : this.axis - 1; + this.axisNormalized = true; + } + + if (!x.glTexture && !x.glTextureFragments) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + } + + this._createIndexMap(x.glTextureShape, x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + const programInputs = [{ + input: x, + name: 'X' + }, { + input: this.normAxisIndexMap, + name: 'normAxisIndexMap' + }]; + + if (this.scale) { + programInputs.push({ + input: this.weights['gamma'], + name: 'gamma' + }); + } + + if (this.center) { + programInputs.push({ + input: this.weights['beta'], + name: 'beta' + }); + } + + programInputs.push({ + input: this.weights['moving_mean'], + name: 'mean' + }); + programInputs.push({ + input: this.weights['moving_variance'], + name: 'std' + }); + const programUniforms = [{ + value: this.epsilon, + type: 'float', + name: 'epsilon' + }, { + value: +this.scale, + type: 'bool', + name: 'scale' + }, { + value: +this.center, + type: 'bool', + name: 'center' + }]; + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: programInputs, + uniforms: programUniforms, + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = BatchNormalization; \ No newline at end of file diff --git a/keras-js/lib/layers/normalization/index.js b/keras-js/lib/layers/normalization/index.js new file mode 100644 index 0000000000..7985bce8aa --- /dev/null +++ b/keras-js/lib/layers/normalization/index.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "BatchNormalization", { + enumerable: true, + get: function () { + return _BatchNormalization.default; + } +}); + +var _BatchNormalization = _interopRequireDefault(require("./BatchNormalization")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/AveragePooling1D.js b/keras-js/lib/layers/pooling/AveragePooling1D.js new file mode 100644 index 0000000000..0ddbe25d2c --- /dev/null +++ b/keras-js/lib/layers/pooling/AveragePooling1D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling1D2 = _interopRequireDefault(require("./_Pooling1D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AveragePooling1D extends _Pooling1D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'AveragePooling1D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = AveragePooling1D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/AveragePooling2D.js b/keras-js/lib/layers/pooling/AveragePooling2D.js new file mode 100644 index 0000000000..b22880d9f8 --- /dev/null +++ b/keras-js/lib/layers/pooling/AveragePooling2D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling2D2 = _interopRequireDefault(require("./_Pooling2D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AveragePooling2D extends _Pooling2D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'AveragePooling2D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = AveragePooling2D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/AveragePooling3D.js b/keras-js/lib/layers/pooling/AveragePooling3D.js new file mode 100644 index 0000000000..a54a3e2d0b --- /dev/null +++ b/keras-js/lib/layers/pooling/AveragePooling3D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling3D2 = _interopRequireDefault(require("./_Pooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AveragePooling3D extends _Pooling3D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'AveragePooling3D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = AveragePooling3D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/GlobalAveragePooling1D.js b/keras-js/lib/layers/pooling/GlobalAveragePooling1D.js new file mode 100644 index 0000000000..741125c09c --- /dev/null +++ b/keras-js/lib/layers/pooling/GlobalAveragePooling1D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling1D2 = _interopRequireDefault(require("./_GlobalPooling1D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalAveragePooling1D extends _GlobalPooling1D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalAveragePooling1D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = GlobalAveragePooling1D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/GlobalAveragePooling2D.js b/keras-js/lib/layers/pooling/GlobalAveragePooling2D.js new file mode 100644 index 0000000000..195f3a3787 --- /dev/null +++ b/keras-js/lib/layers/pooling/GlobalAveragePooling2D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling2D2 = _interopRequireDefault(require("./_GlobalPooling2D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalAveragePooling2D extends _GlobalPooling2D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalAveragePooling2D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = GlobalAveragePooling2D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/GlobalAveragePooling3D.js b/keras-js/lib/layers/pooling/GlobalAveragePooling3D.js new file mode 100644 index 0000000000..9c9c95e6a6 --- /dev/null +++ b/keras-js/lib/layers/pooling/GlobalAveragePooling3D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling3D2 = _interopRequireDefault(require("./_GlobalPooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalAveragePooling3D extends _GlobalPooling3D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalAveragePooling3D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = GlobalAveragePooling3D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/GlobalMaxPooling1D.js b/keras-js/lib/layers/pooling/GlobalMaxPooling1D.js new file mode 100644 index 0000000000..bbc6871b6b --- /dev/null +++ b/keras-js/lib/layers/pooling/GlobalMaxPooling1D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling1D2 = _interopRequireDefault(require("./_GlobalPooling1D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalMaxPooling1D extends _GlobalPooling1D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalMaxPooling1D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = GlobalMaxPooling1D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/GlobalMaxPooling2D.js b/keras-js/lib/layers/pooling/GlobalMaxPooling2D.js new file mode 100644 index 0000000000..532eed4613 --- /dev/null +++ b/keras-js/lib/layers/pooling/GlobalMaxPooling2D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling2D2 = _interopRequireDefault(require("./_GlobalPooling2D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalMaxPooling2D extends _GlobalPooling2D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalMaxPooling2D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = GlobalMaxPooling2D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/GlobalMaxPooling3D.js b/keras-js/lib/layers/pooling/GlobalMaxPooling3D.js new file mode 100644 index 0000000000..cd7de61e57 --- /dev/null +++ b/keras-js/lib/layers/pooling/GlobalMaxPooling3D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling3D2 = _interopRequireDefault(require("./_GlobalPooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalMaxPooling3D extends _GlobalPooling3D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalMaxPooling3D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = GlobalMaxPooling3D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/MaxPooling1D.js b/keras-js/lib/layers/pooling/MaxPooling1D.js new file mode 100644 index 0000000000..01b7d1c47a --- /dev/null +++ b/keras-js/lib/layers/pooling/MaxPooling1D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling1D2 = _interopRequireDefault(require("./_Pooling1D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class MaxPooling1D extends _Pooling1D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'MaxPooling1D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = MaxPooling1D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/MaxPooling2D.js b/keras-js/lib/layers/pooling/MaxPooling2D.js new file mode 100644 index 0000000000..814efd789d --- /dev/null +++ b/keras-js/lib/layers/pooling/MaxPooling2D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling2D2 = _interopRequireDefault(require("./_Pooling2D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class MaxPooling2D extends _Pooling2D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'MaxPooling2D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = MaxPooling2D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/MaxPooling3D.js b/keras-js/lib/layers/pooling/MaxPooling3D.js new file mode 100644 index 0000000000..0815b92973 --- /dev/null +++ b/keras-js/lib/layers/pooling/MaxPooling3D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling3D2 = _interopRequireDefault(require("./_Pooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class MaxPooling3D extends _Pooling3D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'MaxPooling3D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = MaxPooling3D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/_GlobalPooling1D.js b/keras-js/lib/layers/pooling/_GlobalPooling1D.js new file mode 100644 index 0000000000..43020e2b16 --- /dev/null +++ b/keras-js/lib/layers/pooling/_GlobalPooling1D.js @@ -0,0 +1,103 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +class _GlobalPooling1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_GlobalPooling1D'; + const { + data_format = 'channels_last' + } = attrs; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const [steps, features] = x.tensor.shape; + this.output = new _Tensor.default([], [features]); + + for (let i = 0, len = features; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, _ndarrayOps.default.sup(x.tensor.pick(null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, _ndarrayOps.default.sum(x.tensor.pick(null, i)) / steps); + } + } + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + + if (!this.output) { + this.output = new _Tensor.default([], [this.inputShape[1]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const isMaxPooling = this.poolingFunc === 'max'; + + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = _GlobalPooling1D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/_GlobalPooling2D.js b/keras-js/lib/layers/pooling/_GlobalPooling2D.js new file mode 100644 index 0000000000..db587281c3 --- /dev/null +++ b/keras-js/lib/layers/pooling/_GlobalPooling2D.js @@ -0,0 +1,113 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +class _GlobalPooling2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_GlobalPooling2D'; + const { + data_format = 'channels_last' + } = attrs; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + const [rows, cols, channels] = x.tensor.shape; + this.output = new _Tensor.default([], [channels]); + + for (let i = 0, len = channels; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, _ndarrayOps.default.sup(x.tensor.pick(null, null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, _ndarrayOps.default.sum(x.tensor.pick(null, null, i)) / (rows * cols)); + } + } + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [this.inputShape[2]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const isMaxPooling = this.poolingFunc === 'max'; + + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0] * this.inputShape[1], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = _GlobalPooling2D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/_GlobalPooling3D.js b/keras-js/lib/layers/pooling/_GlobalPooling3D.js new file mode 100644 index 0000000000..7aaa74e696 --- /dev/null +++ b/keras-js/lib/layers/pooling/_GlobalPooling3D.js @@ -0,0 +1,113 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +class _GlobalPooling3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_GlobalPooling3D'; + const { + data_format = 'channels_last' + } = attrs; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + const [dim1, dim2, dim3, channels] = x.tensor.shape; + this.output = new _Tensor.default([], [channels]); + + for (let i = 0, len = channels; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, _ndarrayOps.default.sup(x.tensor.pick(null, null, null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, _ndarrayOps.default.sum(x.tensor.pick(null, null, null, i)) / (dim1 * dim2 * dim3)); + } + } + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [this.inputShape[3]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const isMaxPooling = this.poolingFunc === 'max'; + + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0] * this.inputShape[1] * this.inputShape[2], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = _GlobalPooling3D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/_Pooling1D.js b/keras-js/lib/layers/pooling/_Pooling1D.js new file mode 100644 index 0000000000..59fa7bfadd --- /dev/null +++ b/keras-js/lib/layers/pooling/_Pooling1D.js @@ -0,0 +1,210 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +const poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +class _Pooling1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_Pooling1D'; + const { + pool_size = 2, + strides = null, + padding = 'valid' + } = attrs; + this.poolSize = pool_size; + this.strides = strides === null ? this.poolSize : strides; + this.padding = padding; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + this.poolingFragmentsProgram = _WebGL.webgl2.compileProgram(poolingFragmentsProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const stepsNew = this.padding === 'valid' ? Math.floor((x.tensor.shape[0] - this.poolSize + this.strides) / this.strides) : Math.floor((x.tensor.shape[0] + this.strides - 1) / this.strides); + this.output = new _Tensor.default([], [stepsNew, x.tensor.shape[1]]); + const outputStep = new _Tensor.default([], [x.tensor.shape[1]]); + let step = this.padding === 'valid' ? 0 : Math.min(0, Math.ceil((x.tensor.shape[0] - (stepsNew - 1) * this.strides - this.poolSize) / 2)); + + for (let i = 0; i < stepsNew; i++) { + let _step = Math.max(0, step); + + let limit = this.poolSize + Math.min(0, step); + + _ndarrayOps.default.assign(outputStep.tensor, x.tensor.pick(_step, null)); + + let count = 1; + + for (let j = 1; j < limit; j++) { + if (_step + j > x.tensor.shape[0] - 1) { + break; + } + + if (this.poolingFunc === 'max') { + _ndarrayOps.default.maxeq(outputStep.tensor, x.tensor.pick(_step + j, null)); + } else if (this.poolingFunc === 'average') { + _ndarrayOps.default.addeq(outputStep.tensor, x.tensor.pick(_step + j, null)); + } + + count += 1; + } + + if (this.poolingFunc === 'average') { + _ndarrayOps.default.divseq(outputStep.tensor, count); + } + + _ndarrayOps.default.assign(this.output.tensor.pick(i, null), outputStep.tensor); + + step += this.strides; + } + } + + _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + const stepsNew = this.padding === 'valid' ? Math.floor((this.inputShape[0] - this.poolSize + this.strides) / this.strides) : Math.floor((this.inputShape[0] + this.strides - 1) / this.strides); + this.outputShape = [stepsNew, this.inputShape[1]]; + this.poolIndexMap = new _Tensor.default([], [stepsNew, this.poolSize], { + type: Int32Array + }); + + _ndarrayOps.default.assigns(this.poolIndexMap.tensor, -1); + + let step = this.padding === 'valid' ? 0 : Math.min(0, Math.ceil((this.inputShape[0] - (stepsNew - 1) * this.strides - this.poolSize) / 2)); + + for (let i = 0; i < stepsNew; i++) { + let _step = Math.max(0, step); + + let limit = this.poolSize + Math.min(0, step); + let inputIndex = _step; + this.poolIndexMap.tensor.set(i, 0, inputIndex); + + for (let j = 1; j < limit; j++) { + inputIndex = _step + j; + + if (inputIndex <= this.inputShape[0] - 1) { + this.poolIndexMap.tensor.set(i, j, inputIndex); + } else { + break; + } + } + + step += this.strides; + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this.inputShape = x.tensor.shape; + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + const isMaxPooling = this.poolingFunc === 'max'; + const programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: this.poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (x.glTextureFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + + _WebGL.webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + + x.removeGLTextureFragmentsAsColStack(); + } else { + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = _Pooling1D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/_Pooling2D.js b/keras-js/lib/layers/pooling/_Pooling2D.js new file mode 100644 index 0000000000..4e3641f00e --- /dev/null +++ b/keras-js/lib/layers/pooling/_Pooling2D.js @@ -0,0 +1,338 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +const poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +class _Pooling2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_Pooling2D'; + const { + pool_size = [2, 2], + strides = null, + padding = 'valid', + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(pool_size)) { + this.poolSize = pool_size; + } else { + this.poolSize = [pool_size, pool_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else if (strides !== null) { + this.strides = [strides, strides]; + } else { + this.strides = this.poolSize; + } + + this.padding = padding; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + this.poolingFragmentsProgram = _WebGL.webgl2.compileProgram(poolingFragmentsProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + const [inputRows, inputCols, inputChannels] = inputShape; + const [nbRow, nbCol] = this.poolSize; + const outputRows = this.padding === 'same' ? Math.floor((inputRows + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputRows - nbRow + this.strides[0]) / this.strides[0]); + const outputCols = this.padding === 'same' ? Math.floor((inputCols + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputCols - nbCol + this.strides[1]) / this.strides[1]); + const paddingRow = this.padding === 'same' ? Math.max(0, Math.floor((outputRows - 1) * this.strides[0] + nbRow - inputRows)) : 0; + const paddingCol = this.padding === 'same' ? Math.max(0, Math.floor((outputCols - 1) * this.strides[1] + nbCol - inputCols)) : 0; + const paddingRowBefore = Math.floor(paddingRow / 2); + const paddingRowAfter = paddingRow - paddingRowBefore; + const paddingColBefore = Math.floor(paddingCol / 2); + const paddingColAfter = paddingCol - paddingColBefore; + this.outputShape = [outputRows, outputCols, inputChannels]; + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]; + } + + _padInput(x) { + if (this.padding === 'same') { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + const newRows = inputRows + paddingRowBefore + paddingRowAfter; + const newCols = inputCols + paddingColBefore + paddingColAfter; + + const _x = new _Tensor.default([], [newRows, newCols, inputChannels]); + + if (this.poolingFunc === 'max') { + _ndarrayOps.default.assigns(_x.tensor, Number.NEGATIVE_INFINITY); + } + + _ndarrayOps.default.assign(_x.tensor.hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels).lo(paddingRowBefore, paddingColBefore, 0), x.tensor); + + return _x; + } + + return x; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this._calcOutputShape(x.tensor.shape); + + x = this._padInput(x); + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const [nbRow, nbCol] = this.poolSize; + this.output = new _Tensor.default([], this.outputShape); + const patch = new _Tensor.default([], [nbRow, nbCol, inputChannels]); + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + + for (let i = 0, _i = 0; i <= inputRows - nbRow; i += this.strides[0], _i++) { + let nbRowInPadding = 0; + + if (i < paddingRowBefore) { + nbRowInPadding = paddingRowBefore - i; + } else if (i + nbRow > inputRows - paddingRowAfter) { + nbRowInPadding = i + nbRow - (inputRows - paddingRowAfter); + } + + for (let j = 0, _j = 0; j <= inputCols - nbCol; j += this.strides[1], _j++) { + let nbColInPadding = 0; + + if (j < paddingColBefore) { + nbColInPadding = paddingColBefore - j; + } else if (j + nbCol > inputCols - paddingColAfter) { + nbColInPadding = j + nbCol - (inputCols - paddingColAfter); + } + + const nbCellsEffective = (nbRow - nbRowInPadding) * (nbCol - nbColInPadding); + + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + nbRow, j + nbCol, inputChannels).lo(i, j, 0)); + + for (let c = 0; c < inputChannels; c++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(_i, _j, c, _ndarrayOps.default.sup(patch.tensor.pick(null, null, c))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(_i, _j, c, _ndarrayOps.default.sum(patch.tensor.pick(null, null, c)) / nbCellsEffective); + } + } + } + } + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + + if (!this.tiledInput) { + this.tiledInput = new _Tensor.default([], [inputRows * inputCols, inputChannels]); + } + + const patch = new _Tensor.default([], [inputRows, inputCols]); + const patchRaveled = new _Tensor.default([], [inputRows * inputCols]); + + for (let c = 0; c < inputChannels; c++) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.pick(null, null, c)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.tiledInput.tensor.pick(null, c), patchRaveled.tensor); + } + + return this.tiledInput; + } + + _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + let inputRows = this.inputShape[0]; + let inputCols = this.inputShape[1]; + const rowIndices = new _Tensor.default([], [inputRows, inputCols]); + let index = 0; + + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + rowIndices.tensor.set(i, j, index); + index += 1; + } + } + + if (this.padding === 'same') { + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + inputRows = inputRows + paddingRowBefore + paddingRowAfter; + inputCols = inputCols + paddingColBefore + paddingColAfter; + + const _rowIndices = new _Tensor.default([], [inputRows, inputCols]); + + _ndarrayOps.default.assigns(_rowIndices.tensor, -1); + + _ndarrayOps.default.assign(_rowIndices.tensor.hi(this.inputShape[0] + paddingRowBefore, this.inputShape[1] + paddingColBefore).lo(paddingRowBefore, paddingColBefore), rowIndices.tensor); + + rowIndices.tensor = _rowIndices.tensor; + } + + const [nbRow, nbCol] = this.poolSize; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + this.poolIndexMap = new _Tensor.default([], [outputRows * outputCols, nbRow * nbCol], { + type: Int32Array + }); + const patchRow = new _Tensor.default([], [nbRow, nbCol]); + let offset = 0; + + for (let i = 0, limit = inputRows - nbRow; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbCol; j <= limit; j += this.strides[1]) { + _ndarrayOps.default.assign(patchRow.tensor, rowIndices.tensor.hi(i + nbRow, j + nbCol).lo(i, j)); + + this.poolIndexMap.tensor.data.set(patchRow.tensor.data, offset); + offset += nbRow * nbCol; + } + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + + this._im2col(x); + + this.tiledInput.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(); + + if (!this.output) { + const [outputRows, outputCols, inputChannels] = this.outputShape; + const outputTextureShape = [outputRows * outputCols, inputChannels]; + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.tiledInput; + const poolSize = this.poolSize[0] * this.poolSize[1]; + const isMaxPooling = this.poolingFunc === 'max'; + const programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (input.glTextureFragments) { + input.convert2DRowFragmentedGLTextureToColStack(); + + _WebGL.webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + + input.removeGLTextureFragmentsAsColStack(); + } else { + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + +} + +exports.default = _Pooling2D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/_Pooling3D.js b/keras-js/lib/layers/pooling/_Pooling3D.js new file mode 100644 index 0000000000..652882cf74 --- /dev/null +++ b/keras-js/lib/layers/pooling/_Pooling3D.js @@ -0,0 +1,359 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +const poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +class _Pooling3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_Pooling3D'; + const { + pool_size = [2, 2, 2], + strides = null, + padding = 'valid', + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(pool_size)) { + this.poolSize = pool_size; + } else { + this.poolSize = [pool_size, pool_size, pool_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else if (strides !== null) { + this.strides = [strides, strides, strides]; + } else { + this.strides = this.poolSize; + } + + this.padding = padding; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + this.poolingFragmentsProgram = _WebGL.webgl2.compileProgram(poolingFragmentsProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + const [inputDim1, inputDim2, inputDim3, inputChannels] = inputShape; + const [poolDim1, poolDim2, poolDim3] = this.poolSize; + const outputDim1 = this.padding === 'same' ? Math.floor((inputDim1 + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputDim1 - poolDim1 + this.strides[0]) / this.strides[0]); + const outputDim2 = this.padding === 'same' ? Math.floor((inputDim2 + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputDim2 - poolDim2 + this.strides[1]) / this.strides[1]); + const outputDim3 = this.padding === 'same' ? Math.floor((inputDim3 + this.strides[2] - 1) / this.strides[2]) : Math.floor((inputDim3 - poolDim3 + this.strides[2]) / this.strides[2]); + const paddingDim1 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim1 - 1) * this.strides[0] + poolDim1 - inputDim1)) : 0; + const paddingDim2 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim2 - 1) * this.strides[1] + poolDim2 - inputDim2)) : 0; + const paddingDim3 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim3 - 1) * this.strides[2] + poolDim3 - inputDim3)) : 0; + const paddingDim1Before = Math.floor(paddingDim1 / 2); + const paddingDim1After = paddingDim1 - paddingDim1Before; + const paddingDim2Before = Math.floor(paddingDim2 / 2); + const paddingDim2After = paddingDim2 - paddingDim2Before; + const paddingDim3Before = Math.floor(paddingDim3 / 2); + const paddingDim3After = paddingDim3 - paddingDim3Before; + this.outputShape = [outputDim1, outputDim2, outputDim3, inputChannels]; + this.inputPadding = [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After]; + } + + _padInput(x) { + if (this.padding === 'same') { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + const newDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + const newDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + const newDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + + const _x = new _Tensor.default([], [newDim1, newDim2, newDim3, inputChannels]); + + if (this.poolingFunc === 'max') { + _ndarrayOps.default.assigns(_x.tensor, Number.NEGATIVE_INFINITY); + } + + _ndarrayOps.default.assign(_x.tensor.hi(inputDim1 + paddingDim1Before, inputDim2 + paddingDim2Before, inputDim3 + paddingDim3Before, inputChannels).lo(paddingDim1Before, paddingDim2Before, paddingDim3Before, 0), x.tensor); + + return _x; + } + + return x; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this._calcOutputShape(x.tensor.shape); + + x = this._padInput(x); + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + const [poolDim1, poolDim2, poolDim3] = this.poolSize; + this.output = new _Tensor.default([], this.outputShape); + let patch = new _Tensor.default([], [poolDim1, poolDim2, poolDim3, inputChannels]); + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + + for (let i = 0, _i = 0; i <= inputDim1 - poolDim1; i += this.strides[0], _i++) { + let dim1InPadding = 0; + + if (i < paddingDim1Before) { + dim1InPadding = paddingDim1Before - i; + } else if (i + poolDim1 > inputDim1 - paddingDim1After) { + dim1InPadding = i + poolDim1 - (inputDim1 - paddingDim1After); + } + + for (let j = 0, _j = 0; j <= inputDim2 - poolDim2; j += this.strides[1], _j++) { + let dim2InPadding = 0; + + if (j < paddingDim2Before) { + dim2InPadding = paddingDim2Before - j; + } else if (j + poolDim2 > inputDim2 - paddingDim2After) { + dim2InPadding = j + poolDim2 - (inputDim2 - paddingDim2After); + } + + for (let k = 0, _k = 0; k <= inputDim3 - poolDim3; k += this.strides[2], _k++) { + let dim3InPadding = 0; + + if (k < paddingDim3Before) { + dim3InPadding = paddingDim3Before - k; + } else if (k + poolDim3 > inputDim3 - paddingDim3After) { + dim3InPadding = k + poolDim3 - (inputDim3 - paddingDim3After); + } + + const nbCellsEffective = (poolDim1 - dim1InPadding) * (poolDim2 - dim2InPadding) * (poolDim3 - dim3InPadding); + + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + poolDim1, j + poolDim2, k + poolDim3, inputChannels).lo(i, j, k, 0)); + + for (let c = 0; c < inputChannels; c++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(_i, _j, _k, c, _ndarrayOps.default.sup(patch.tensor.pick(null, null, null, c))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(_i, _j, _k, c, _ndarrayOps.default.sum(patch.tensor.pick(null, null, null, c)) / nbCellsEffective); + } + } + } + } + } + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _vol2col(x) { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + + if (!this.tiledInput) { + this.tiledInput = new _Tensor.default([], [inputDim1 * inputDim2 * inputDim3, inputChannels]); + } + + const patch = new _Tensor.default([], [inputDim1, inputDim2, inputDim3]); + const patchRaveled = new _Tensor.default([], [inputDim1 * inputDim2 * inputDim3]); + + for (let c = 0; c < inputChannels; c++) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.pick(null, null, null, c)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.tiledInput.tensor.pick(null, c), patchRaveled.tensor); + } + + return this.tiledInput; + } + + _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + let inputDim1 = this.inputShape[0]; + let inputDim2 = this.inputShape[1]; + let inputDim3 = this.inputShape[2]; + const rowIndices = new _Tensor.default([], [inputDim1, inputDim2, inputDim3]); + let index = 0; + + for (let i = 0; i < inputDim1; i++) { + for (let j = 0; j < inputDim2; j++) { + for (let k = 0; k < inputDim3; k++) { + rowIndices.tensor.set(i, j, k, index); + index += 1; + } + } + } + + if (this.padding === 'same') { + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + inputDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + inputDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + inputDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + + const _rowIndices = new _Tensor.default([], [inputDim1, inputDim2, inputDim3]); + + _ndarrayOps.default.assigns(_rowIndices.tensor, -1); + + _ndarrayOps.default.assign(_rowIndices.tensor.hi(this.inputShape[0] + paddingDim1Before, this.inputShape[1] + paddingDim2Before, this.inputShape[2] + paddingDim3Before).lo(paddingDim1Before, paddingDim2Before, paddingDim3Before), rowIndices.tensor); + + rowIndices.tensor = _rowIndices.tensor; + } + + const [poolDim1, poolDim2, poolDim3] = this.poolSize; + const outputDim1 = this.outputShape[0]; + const outputDim2 = this.outputShape[1]; + const outputDim3 = this.outputShape[2]; + this.poolIndexMap = new _Tensor.default([], [outputDim1 * outputDim2 * outputDim3, poolDim1 * poolDim2 * poolDim3], { + type: Int32Array + }); + const patchRow = new _Tensor.default([], [poolDim1, poolDim2, poolDim3]); + let offset = 0; + + for (let i = 0, limit = inputDim1 - poolDim1; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - poolDim2; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - poolDim3; k <= limit; k += this.strides[2]) { + _ndarrayOps.default.assign(patchRow.tensor, rowIndices.tensor.hi(i + poolDim1, j + poolDim2, k + poolDim3).lo(i, j, k)); + + this.poolIndexMap.tensor.data.set(patchRow.tensor.data, offset); + offset += poolDim1 * poolDim2 * poolDim3; + } + } + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + + this._vol2col(x); + + this.tiledInput.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(); + + if (!this.output) { + const [outputDim1, outputDim2, outputDim3, inputChannels] = this.outputShape; + const outputTextureShape = [outputDim1 * outputDim2 * outputDim3, inputChannels]; + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.tiledInput; + const poolSize = this.poolSize[0] * this.poolSize[1] * this.poolSize[2]; + const isMaxPooling = this.poolingFunc === 'max'; + const programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (input.glTextureFragments) { + input.convert2DRowFragmentedGLTextureToColStack(); + + _WebGL.webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + + input.removeGLTextureFragmentsAsColStack(); + } else { + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + } + +} + +exports.default = _Pooling3D; \ No newline at end of file diff --git a/keras-js/lib/layers/pooling/index.js b/keras-js/lib/layers/pooling/index.js new file mode 100644 index 0000000000..6774b8b615 --- /dev/null +++ b/keras-js/lib/layers/pooling/index.js @@ -0,0 +1,103 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "MaxPooling1D", { + enumerable: true, + get: function () { + return _MaxPooling1D.default; + } +}); +Object.defineProperty(exports, "MaxPooling2D", { + enumerable: true, + get: function () { + return _MaxPooling2D.default; + } +}); +Object.defineProperty(exports, "MaxPooling3D", { + enumerable: true, + get: function () { + return _MaxPooling3D.default; + } +}); +Object.defineProperty(exports, "AveragePooling1D", { + enumerable: true, + get: function () { + return _AveragePooling1D.default; + } +}); +Object.defineProperty(exports, "AveragePooling2D", { + enumerable: true, + get: function () { + return _AveragePooling2D.default; + } +}); +Object.defineProperty(exports, "AveragePooling3D", { + enumerable: true, + get: function () { + return _AveragePooling3D.default; + } +}); +Object.defineProperty(exports, "GlobalMaxPooling1D", { + enumerable: true, + get: function () { + return _GlobalMaxPooling1D.default; + } +}); +Object.defineProperty(exports, "GlobalMaxPooling2D", { + enumerable: true, + get: function () { + return _GlobalMaxPooling2D.default; + } +}); +Object.defineProperty(exports, "GlobalMaxPooling3D", { + enumerable: true, + get: function () { + return _GlobalMaxPooling3D.default; + } +}); +Object.defineProperty(exports, "GlobalAveragePooling1D", { + enumerable: true, + get: function () { + return _GlobalAveragePooling1D.default; + } +}); +Object.defineProperty(exports, "GlobalAveragePooling2D", { + enumerable: true, + get: function () { + return _GlobalAveragePooling2D.default; + } +}); +Object.defineProperty(exports, "GlobalAveragePooling3D", { + enumerable: true, + get: function () { + return _GlobalAveragePooling3D.default; + } +}); + +var _MaxPooling1D = _interopRequireDefault(require("./MaxPooling1D")); + +var _MaxPooling2D = _interopRequireDefault(require("./MaxPooling2D")); + +var _MaxPooling3D = _interopRequireDefault(require("./MaxPooling3D")); + +var _AveragePooling1D = _interopRequireDefault(require("./AveragePooling1D")); + +var _AveragePooling2D = _interopRequireDefault(require("./AveragePooling2D")); + +var _AveragePooling3D = _interopRequireDefault(require("./AveragePooling3D")); + +var _GlobalMaxPooling1D = _interopRequireDefault(require("./GlobalMaxPooling1D")); + +var _GlobalMaxPooling2D = _interopRequireDefault(require("./GlobalMaxPooling2D")); + +var _GlobalMaxPooling3D = _interopRequireDefault(require("./GlobalMaxPooling3D")); + +var _GlobalAveragePooling1D = _interopRequireDefault(require("./GlobalAveragePooling1D")); + +var _GlobalAveragePooling2D = _interopRequireDefault(require("./GlobalAveragePooling2D")); + +var _GlobalAveragePooling3D = _interopRequireDefault(require("./GlobalAveragePooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/recurrent/GRU.js b/keras-js/lib/layers/recurrent/GRU.js new file mode 100644 index 0000000000..6bf7c72d37 --- /dev/null +++ b/keras-js/lib/layers/recurrent/GRU.js @@ -0,0 +1,682 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var activations = _interopRequireWildcard(require("../../activations")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _cwise = _interopRequireDefault(require("cwise")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; +const gateSummationProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nuniform sampler2D bias;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(bias, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n float bias_val = texelFetch(bias, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val + t2_val + bias_val);\r\n}\r\n"; +const gateProductProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(t1, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val * t2_val);\r\n}\r\n"; +const timestepReadProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n\r\n outColor = vec4(texelFetch(x, ivec2(out_x, index), 0).r);\r\n}\r\n"; +const timestepWriteProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D y;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(y, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (out_y == index) {\r\n outColor = vec4(texelFetch(x, ivec2(out_x, 0), 0).r);\r\n } else {\r\n outColor = vec4(texelFetch(y, ivec2(out_x, out_y), 0).r);\r\n }\r\n}\r\n"; +const updateProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D h;\r\nuniform sampler2D htm1;\r\nuniform sampler2D z;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(h, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float h_val = texelFetch(h, ivec2(out_x, out_y), 0).r;\r\n float htm1_val = texelFetch(htm1, ivec2(out_x, out_y), 0).r;\r\n float z_val = texelFetch(z, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(h_val * (float(1.0) - z_val) + htm1_val * z_val);\r\n}\r\n"; + +class GRU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + Object.defineProperty(this, "_combine", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array', 'array'], + body: function (_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b; + } + }) + }); + Object.defineProperty(this, "_update", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array'], + body: function (_h, _htm1, _z) { + _h = _h * (1 - _z) + _htm1 * _z; + } + }) + }); + this.layerClass = 'GRU'; + const { + units = 1, + activation = 'tanh', + use_bias = true, + recurrent_activation = 'hard_sigmoid', + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs; + this.units = units; + this.activation = activation; + this.recurrentActivation = recurrent_activation; + this.activationFunc = activations[activation]; + this.recurrentActivationFunc = activations[recurrent_activation]; + this.use_bias = use_bias; + this.returnSequences = return_sequences; + this.goBackwards = go_backwards; + this.stateful = stateful; + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel']; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + this.recurrentActivationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.recurrentActivation]); + this.gateSummationProgram = _WebGL.webgl2.compileProgram(gateSummationProgramSource); + this.gateProductProgram = _WebGL.webgl2.compileProgram(gateProductProgramSource); + this.timestepReadProgram = _WebGL.webgl2.compileProgram(timestepReadProgramSource); + this.timestepWriteProgram = _WebGL.webgl2.compileProgram(timestepWriteProgramSource); + this.updateProgram = _WebGL.webgl2.compileProgram(updateProgramSource); + } + } + + setWeights(weightsArr) { + super.setWeights(weightsArr); + const shape_W = this.weights['kernel'].tensor.shape; + this.weights['W_z'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_r'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_h'] = new _Tensor.default([], [shape_W[0], this.units]); + + _ndarrayOps.default.assign(this.weights['W_z'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], this.units).lo(0, 0)); + + _ndarrayOps.default.assign(this.weights['W_r'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 2 * this.units).lo(0, this.units)); + + _ndarrayOps.default.assign(this.weights['W_h'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 3 * this.units).lo(0, 2 * this.units)); + + const shape_U = this.weights['recurrent_kernel'].tensor.shape; + this.weights['U_z'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_r'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_h'] = new _Tensor.default([], [shape_U[0], this.units]); + + _ndarrayOps.default.assign(this.weights['U_z'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], this.units).lo(0, 0)); + + _ndarrayOps.default.assign(this.weights['U_r'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 2 * this.units).lo(0, this.units)); + + _ndarrayOps.default.assign(this.weights['U_h'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 3 * this.units).lo(0, 2 * this.units)); + + this.weights['b_z'] = new _Tensor.default([], [this.units]); + this.weights['b_r'] = new _Tensor.default([], [this.units]); + this.weights['b_h'] = new _Tensor.default([], [this.units]); + + if (this.use_bias) { + _ndarrayOps.default.assign(this.weights['b_z'].tensor, this.weights['bias'].tensor.hi(this.units).lo(0)); + + _ndarrayOps.default.assign(this.weights['b_r'].tensor, this.weights['bias'].tensor.hi(2 * this.units).lo(this.units)); + + _ndarrayOps.default.assign(this.weights['b_h'].tensor, this.weights['bias'].tensor.hi(3 * this.units).lo(2 * this.units)); + } + + if (this.gpu) { + const names = ['W_z', 'W_r', 'W_h', 'U_z', 'U_r', 'U_h', 'b_z', 'b_r', 'b_h']; + names.forEach(name => { + this.weights[name].createGLTexture({ + type: '2d', + format: 'float' + }); + }); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const dimUpdateGate = this.weights['b_z'].tensor.shape[0]; + const dimResetGate = this.weights['b_r'].tensor.shape[0]; + const dimHiddenState = this.weights['b_h'].tensor.shape[0]; + const currentUpdateGateState = new _Tensor.default([], [dimUpdateGate]); + const tempXZ = new _Tensor.default([], [dimUpdateGate]); + const tempHZ = new _Tensor.default([], [dimUpdateGate]); + const currentResetGateState = new _Tensor.default([], [dimResetGate]); + const tempXR = new _Tensor.default([], [dimResetGate]); + const tempHR = new _Tensor.default([], [dimResetGate]); + const currentHiddenState = this.stateful && this.currentHiddenState ? this.currentHiddenState : new _Tensor.default([], [dimHiddenState]); + const tempXH = new _Tensor.default([], [dimHiddenState]); + const tempHH = new _Tensor.default([], [dimHiddenState]); + const previousHiddenState = new _Tensor.default([], [dimHiddenState]); + this.hiddenStateSequence = new _Tensor.default([], [x.tensor.shape[0], dimHiddenState]); + const currentX = new _Tensor.default([], [x.tensor.shape[1]]); + + const _step = () => { + _ndarrayOps.default.assign(previousHiddenState.tensor, currentHiddenState.tensor); + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_z'].tensor.transpose(1, 0), currentX.tensor, 1, tempXZ.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_z'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHZ.tensor); + + this._combine(currentUpdateGateState.tensor, tempXZ.tensor, tempHZ.tensor, this.weights['b_z'].tensor); + + this.recurrentActivationFunc(currentUpdateGateState); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_r'].tensor.transpose(1, 0), currentX.tensor, 1, tempXR.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_r'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHR.tensor); + + this._combine(currentResetGateState.tensor, tempXR.tensor, tempHR.tensor, this.weights['b_r'].tensor); + + this.recurrentActivationFunc(currentResetGateState); + + _ndarrayOps.default.muleq(currentResetGateState.tensor, previousHiddenState.tensor); + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_h'].tensor.transpose(1, 0), currentX.tensor, 1, tempXH.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_h'].tensor.transpose(1, 0), currentResetGateState.tensor, 1, tempHH.tensor); + + this._combine(currentHiddenState.tensor, tempXH.tensor, tempHH.tensor, this.weights['b_h'].tensor); + + this.activationFunc(currentHiddenState); + + this._update(currentHiddenState.tensor, previousHiddenState.tensor, currentUpdateGateState.tensor); + }; + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _ndarrayOps.default.assign(currentX.tensor, x.tensor.pick(inputIndex, null)); + + const tempTensors = [tempXZ, tempHZ, tempXR, tempHR, tempXH, tempHH]; + tempTensors.forEach(temp => _ndarrayOps.default.assigns(temp.tensor, 0)); + + _step(); + + if (this.returnSequences) { + _ndarrayOps.default.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = currentHiddenState; + } + + if (this.stateful) { + this.currentHiddenState = currentHiddenState; + } + } + + _stepGPU() { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ + input: this.currentHiddenState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXZ, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_z'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHZ, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_z'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentUpdateGateStatePreactiv, + inputs: [{ + input: this.tempXZ, + name: 't1' + }, { + input: this.tempHZ, + name: 't2' + }, { + input: this.weights['b_z'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentUpdateGateState, + inputs: [{ + input: this.currentUpdateGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentUpdateGateState = this.currentUpdateGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXR, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_r'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHR, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_r'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentResetGateStatePreactiv, + inputs: [{ + input: this.tempXR, + name: 't1' + }, { + input: this.tempHR, + name: 't2' + }, { + input: this.weights['b_r'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentResetGateState, + inputs: [{ + input: this.currentResetGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentResetGateState = this.currentResetGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentResetGateStateCopy, + inputs: [{ + input: this.currentResetGateState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateProductProgram, + output: this.currentResetGateState, + inputs: [{ + input: this.currentResetGateStateCopy, + name: 't1' + }, { + input: this.previousHiddenState, + name: 't2' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXH, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_h'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHH, + inputs: [{ + input: this.currentResetGateState, + name: 'A' + }, { + input: this.weights['U_h'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentHiddenStatePreactiv, + inputs: [{ + input: this.tempXH, + name: 't1' + }, { + input: this.tempHH, + name: 't2' + }, { + input: this.weights['b_h'], + name: 'bias' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.currentHiddenState, + inputs: [{ + input: this.currentHiddenStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentHiddenState = this.currentHiddenStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentHiddenStateCopy, + inputs: [{ + input: this.currentHiddenState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.updateProgram, + output: this.currentHiddenState, + inputs: [{ + input: this.currentHiddenStateCopy, + name: 'h' + }, { + input: this.previousHiddenState, + name: 'htm1' + }, { + input: this.currentUpdateGateState, + name: 'z' + }] + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const dimUpdateGate = this.weights['b_z'].glTextureShape[1]; + const dimResetGate = this.weights['b_r'].glTextureShape[1]; + const dimHiddenState = this.weights['b_h'].glTextureShape[1]; + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentHiddenStateCopy) { + this.currentHiddenStateCopy = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenStateCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentHiddenStatePreactiv) { + this.currentHiddenStatePreactiv = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentUpdateGateState) { + this.currentUpdateGateState = new _Tensor.default([], [dimUpdateGate]); + this.currentUpdateGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentUpdateGateStatePreactiv) { + this.currentUpdateGateStatePreactiv = new _Tensor.default([], [dimUpdateGate]); + this.currentUpdateGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXZ) { + this.tempXZ = new _Tensor.default([], [dimUpdateGate]); + this.tempXZ.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHZ) { + this.tempHZ = new _Tensor.default([], [dimUpdateGate]); + this.tempHZ.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentResetGateState) { + this.currentResetGateState = new _Tensor.default([], [dimResetGate]); + this.currentResetGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentResetGateStateCopy) { + this.currentResetGateStateCopy = new _Tensor.default([], [dimResetGate]); + this.currentResetGateStateCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentResetGateStatePreactiv) { + this.currentResetGateStatePreactiv = new _Tensor.default([], [dimResetGate]); + this.currentResetGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXR) { + this.tempXR = new _Tensor.default([], [dimResetGate]); + this.tempXR.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHR) { + this.tempHR = new _Tensor.default([], [dimResetGate]); + this.tempHR.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXH) { + this.tempXH = new _Tensor.default([], [dimHiddenState]); + this.tempXH.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHH) { + this.tempHH = new _Tensor.default([], [dimHiddenState]); + this.tempHH.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.previousHiddenState) { + this.previousHiddenState = new _Tensor.default([], [dimHiddenState]); + this.previousHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new _Tensor.default([], [x.glTextureShape[0], dimHiddenState]); + this.hiddenStateSequence.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new _Tensor.default([], [x.glTextureShape[0], dimHiddenState]); + this.hiddenStateSequenceCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentX) { + this.currentX = new _Tensor.default([], [x.glTextureShape[1]]); + this.currentX.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _WebGL.webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: inputIndex, + type: 'int', + name: 'index' + }] + }); + + this._stepGPU(); + + if (this.returnSequences) { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ + input: this.hiddenStateSequence, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ + input: this.currentHiddenState, + name: 'x' + }, { + input: this.hiddenStateSequenceCopy, + name: 'y' + }], + uniforms: [{ + value: i, + type: 'int', + name: 'index' + }] + }); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = this.currentHiddenState; + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = GRU; \ No newline at end of file diff --git a/keras-js/lib/layers/recurrent/LSTM.js b/keras-js/lib/layers/recurrent/LSTM.js new file mode 100644 index 0000000000..66e38fb29c --- /dev/null +++ b/keras-js/lib/layers/recurrent/LSTM.js @@ -0,0 +1,833 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var activations = _interopRequireWildcard(require("../../activations")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _cwise = _interopRequireDefault(require("cwise")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; +const gateSummationProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nuniform sampler2D bias;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(bias, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n float bias_val = texelFetch(bias, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val + t2_val + bias_val);\r\n}\r\n"; +const gateProductProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(t1, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val * t2_val);\r\n}\r\n"; +const timestepReadProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n\r\n outColor = vec4(texelFetch(x, ivec2(out_x, index), 0).r);\r\n}\r\n"; +const timestepWriteProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D y;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(y, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (out_y == index) {\r\n outColor = vec4(texelFetch(x, ivec2(out_x, 0), 0).r);\r\n } else {\r\n outColor = vec4(texelFetch(y, ivec2(out_x, out_y), 0).r);\r\n }\r\n}\r\n"; +const updateProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D c;\r\nuniform sampler2D ctm1;\r\nuniform sampler2D i;\r\nuniform sampler2D f;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(c, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float c_val = texelFetch(c, ivec2(out_x, out_y), 0).r;\r\n float ctm1_val = texelFetch(ctm1, ivec2(out_x, out_y), 0).r;\r\n float i_val = texelFetch(i, ivec2(out_x, out_y), 0).r;\r\n float f_val = texelFetch(f, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(c_val * i_val + ctm1_val * f_val);\r\n}\r\n"; + +class LSTM extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + Object.defineProperty(this, "_combine", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array', 'array'], + body: function (_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b; + } + }) + }); + Object.defineProperty(this, "_update", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array', 'array'], + body: function (_c, _ctm1, _i, _f) { + _c = _c * _i + _ctm1 * _f; + } + }) + }); + this.layerClass = 'LSTM'; + const { + units = 1, + activation = 'tanh', + use_bias = true, + recurrent_activation = 'hard_sigmoid', + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs; + this.units = units; + this.activation = activation; + this.recurrentActivation = recurrent_activation; + this.activationFunc = activations[activation]; + this.recurrentActivationFunc = activations[recurrent_activation]; + this.use_bias = use_bias; + this.returnSequences = return_sequences; + this.goBackwards = go_backwards; + this.stateful = stateful; + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel']; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + this.recurrentActivationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.recurrentActivation]); + this.gateSummationProgram = _WebGL.webgl2.compileProgram(gateSummationProgramSource); + this.gateProductProgram = _WebGL.webgl2.compileProgram(gateProductProgramSource); + this.timestepReadProgram = _WebGL.webgl2.compileProgram(timestepReadProgramSource); + this.timestepWriteProgram = _WebGL.webgl2.compileProgram(timestepWriteProgramSource); + this.updateProgram = _WebGL.webgl2.compileProgram(updateProgramSource); + } + } + + setWeights(weightsArr) { + super.setWeights(weightsArr); + const shape_W = this.weights['kernel'].tensor.shape; + this.weights['W_i'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_f'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_c'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_o'] = new _Tensor.default([], [shape_W[0], this.units]); + + _ndarrayOps.default.assign(this.weights['W_i'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], this.units).lo(0, 0)); + + _ndarrayOps.default.assign(this.weights['W_f'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 2 * this.units).lo(0, this.units)); + + _ndarrayOps.default.assign(this.weights['W_c'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 3 * this.units).lo(0, 2 * this.units)); + + _ndarrayOps.default.assign(this.weights['W_o'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 4 * this.units).lo(0, 3 * this.units)); + + const shape_U = this.weights['recurrent_kernel'].tensor.shape; + this.weights['U_i'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_f'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_c'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_o'] = new _Tensor.default([], [shape_U[0], this.units]); + + _ndarrayOps.default.assign(this.weights['U_i'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], this.units).lo(0, 0)); + + _ndarrayOps.default.assign(this.weights['U_f'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 2 * this.units).lo(0, this.units)); + + _ndarrayOps.default.assign(this.weights['U_c'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 3 * this.units).lo(0, 2 * this.units)); + + _ndarrayOps.default.assign(this.weights['U_o'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 4 * this.units).lo(0, 3 * this.units)); + + this.weights['b_i'] = new _Tensor.default([], [this.units]); + this.weights['b_f'] = new _Tensor.default([], [this.units]); + this.weights['b_c'] = new _Tensor.default([], [this.units]); + this.weights['b_o'] = new _Tensor.default([], [this.units]); + + if (this.use_bias) { + _ndarrayOps.default.assign(this.weights['b_i'].tensor, this.weights['bias'].tensor.hi(this.units).lo(0)); + + _ndarrayOps.default.assign(this.weights['b_f'].tensor, this.weights['bias'].tensor.hi(2 * this.units).lo(this.units)); + + _ndarrayOps.default.assign(this.weights['b_c'].tensor, this.weights['bias'].tensor.hi(3 * this.units).lo(2 * this.units)); + + _ndarrayOps.default.assign(this.weights['b_o'].tensor, this.weights['bias'].tensor.hi(4 * this.units).lo(3 * this.units)); + } + + if (this.gpu) { + const names = ['W_i', 'W_f', 'W_c', 'W_o', 'U_i', 'U_f', 'U_c', 'U_o', 'b_i', 'b_f', 'b_c', 'b_o']; + names.forEach(name => { + this.weights[name].createGLTexture({ + type: '2d', + format: 'float' + }); + }); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const dimInputGate = this.weights['b_i'].tensor.shape[0]; + const dimCandidate = this.weights['b_c'].tensor.shape[0]; + const dimForgetGate = this.weights['b_f'].tensor.shape[0]; + const dimOutputGate = this.weights['b_o'].tensor.shape[0]; + const currentInputGateState = new _Tensor.default([], [dimInputGate]); + const tempXI = new _Tensor.default([], [dimInputGate]); + const tempHI = new _Tensor.default([], [dimInputGate]); + const currentForgetGateState = new _Tensor.default([], [dimForgetGate]); + const tempXF = new _Tensor.default([], [dimForgetGate]); + const tempHF = new _Tensor.default([], [dimForgetGate]); + const currentOutputGateState = new _Tensor.default([], [dimOutputGate]); + const tempXO = new _Tensor.default([], [dimOutputGate]); + const tempHO = new _Tensor.default([], [dimOutputGate]); + const currentCandidate = new _Tensor.default([], [dimCandidate]); + const tempXC = new _Tensor.default([], [dimCandidate]); + const tempHC = new _Tensor.default([], [dimCandidate]); + const previousCandidate = this.stateful && this.previousCandidate ? this.previousCandidate : new _Tensor.default([], [dimCandidate]); + const currentHiddenState = this.stateful && this.currentHiddenState ? this.currentHiddenState : new _Tensor.default([], [dimCandidate]); + const previousHiddenState = new _Tensor.default([], [dimCandidate]); + this.hiddenStateSequence = new _Tensor.default([], [x.tensor.shape[0], dimCandidate]); + const currentX = new _Tensor.default([], [x.tensor.shape[1]]); + + const _step = () => { + _ndarrayOps.default.assign(previousHiddenState.tensor, currentHiddenState.tensor); + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_i'].tensor.transpose(1, 0), currentX.tensor, 1, tempXI.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_i'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHI.tensor); + + this._combine(currentInputGateState.tensor, tempXI.tensor, tempHI.tensor, this.weights['b_i'].tensor); + + this.recurrentActivationFunc(currentInputGateState); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_f'].tensor.transpose(1, 0), currentX.tensor, 1, tempXF.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_f'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHF.tensor); + + this._combine(currentForgetGateState.tensor, tempXF.tensor, tempHF.tensor, this.weights['b_f'].tensor); + + this.recurrentActivationFunc(currentForgetGateState); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_o'].tensor.transpose(1, 0), currentX.tensor, 1, tempXO.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_o'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHO.tensor); + + this._combine(currentOutputGateState.tensor, tempXO.tensor, tempHO.tensor, this.weights['b_o'].tensor); + + this.recurrentActivationFunc(currentOutputGateState); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_c'].tensor.transpose(1, 0), currentX.tensor, 1, tempXC.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_c'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHC.tensor); + + this._combine(currentCandidate.tensor, tempXC.tensor, tempHC.tensor, this.weights['b_c'].tensor); + + this.activationFunc(currentCandidate); + + this._update(currentCandidate.tensor, previousCandidate.tensor, currentInputGateState.tensor, currentForgetGateState.tensor); + + _ndarrayOps.default.assign(previousCandidate.tensor, currentCandidate.tensor); + + this.activationFunc(currentCandidate); + + _ndarrayOps.default.mul(currentHiddenState.tensor, currentOutputGateState.tensor, currentCandidate.tensor); + }; + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _ndarrayOps.default.assign(currentX.tensor, x.tensor.pick(inputIndex, null)); + + const tempTensors = [tempXI, tempHI, tempXF, tempHF, tempXO, tempHO, tempXC, tempHC]; + tempTensors.forEach(temp => _ndarrayOps.default.assigns(temp.tensor, 0)); + + _step(); + + _ndarrayOps.default.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor); + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = currentHiddenState; + } + + if (this.stateful) { + this.previousCandidate = previousCandidate; + this.currentHiddenState = currentHiddenState; + } + } + + _stepGPU() { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ + input: this.currentHiddenState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXI, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_i'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHI, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_i'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentInputGateStatePreactiv, + inputs: [{ + input: this.tempXI, + name: 't1' + }, { + input: this.tempHI, + name: 't2' + }, { + input: this.weights['b_i'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentInputGateState, + inputs: [{ + input: this.currentInputGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentInputGateState = this.currentInputGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXF, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_f'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHF, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_f'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentForgetGateStatePreactiv, + inputs: [{ + input: this.tempXF, + name: 't1' + }, { + input: this.tempHF, + name: 't2' + }, { + input: this.weights['b_f'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentForgetGateState, + inputs: [{ + input: this.currentForgetGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentForgetGateState = this.currentForgetGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXO, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_o'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHO, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_o'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentOutputGateStatePreactiv, + inputs: [{ + input: this.tempXO, + name: 't1' + }, { + input: this.tempHO, + name: 't2' + }, { + input: this.weights['b_o'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentOutputGateState, + inputs: [{ + input: this.currentOutputGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentOutputGateState = this.currentOutputGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXC, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_c'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHC, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_c'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentCandidatePreactiv, + inputs: [{ + input: this.tempXC, + name: 't1' + }, { + input: this.tempHC, + name: 't2' + }, { + input: this.weights['b_c'], + name: 'bias' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.currentCandidate, + inputs: [{ + input: this.currentCandidatePreactiv, + name: 'x' + }] + }); + } else { + this.currentCandidate = this.currentCandidatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentCandidateCopy, + inputs: [{ + input: this.currentCandidate, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.updateProgram, + output: this.currentCandidate, + inputs: [{ + input: this.currentCandidateCopy, + name: 'c' + }, { + input: this.previousCandidate, + name: 'ctm1' + }, { + input: this.currentInputGateState, + name: 'i' + }, { + input: this.currentForgetGateState, + name: 'f' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousCandidate, + inputs: [{ + input: this.currentCandidate, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentCandidatePreactiv, + inputs: [{ + input: this.currentCandidate, + name: 'source' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.currentCandidate, + inputs: [{ + input: this.currentCandidatePreactiv, + name: 'x' + }] + }); + } else { + this.currentCandidate = this.currentCandidatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.gateProductProgram, + output: this.currentHiddenState, + inputs: [{ + input: this.currentOutputGateState, + name: 't1' + }, { + input: this.currentCandidate, + name: 't2' + }] + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const dimInputGate = this.weights['b_i'].glTextureShape[1]; + const dimCandidate = this.weights['b_c'].glTextureShape[1]; + const dimForgetGate = this.weights['b_f'].glTextureShape[1]; + const dimOutputGate = this.weights['b_o'].glTextureShape[1]; + + if (!this.currentInputGateState) { + this.currentInputGateState = new _Tensor.default([], [dimInputGate]); + this.currentInputGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentInputGateStatePreactiv) { + this.currentInputGateStatePreactiv = new _Tensor.default([], [dimInputGate]); + this.currentInputGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXI) { + this.tempXI = new _Tensor.default([], [dimInputGate]); + this.tempXI.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHI) { + this.tempHI = new _Tensor.default([], [dimInputGate]); + this.tempHI.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentForgetGateState) { + this.currentForgetGateState = new _Tensor.default([], [dimForgetGate]); + this.currentForgetGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentForgetGateStatePreactiv) { + this.currentForgetGateStatePreactiv = new _Tensor.default([], [dimForgetGate]); + this.currentForgetGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXF) { + this.tempXF = new _Tensor.default([], [dimForgetGate]); + this.tempXF.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHF) { + this.tempHF = new _Tensor.default([], [dimForgetGate]); + this.tempHF.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentOutputGateState) { + this.currentOutputGateState = new _Tensor.default([], [dimOutputGate]); + this.currentOutputGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentOutputGateStatePreactiv) { + this.currentOutputGateStatePreactiv = new _Tensor.default([], [dimOutputGate]); + this.currentOutputGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXO) { + this.tempXO = new _Tensor.default([], [dimOutputGate]); + this.tempXO.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHO) { + this.tempHO = new _Tensor.default([], [dimOutputGate]); + this.tempHO.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentCandidate) { + this.currentCandidate = new _Tensor.default([], [dimCandidate]); + this.currentCandidate.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentCandidateCopy) { + this.currentCandidateCopy = new _Tensor.default([], [dimCandidate]); + this.currentCandidateCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentCandidatePreactiv) { + this.currentCandidatePreactiv = new _Tensor.default([], [dimCandidate]); + this.currentCandidatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXC) { + this.tempXC = new _Tensor.default([], [dimCandidate]); + this.tempXC.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHC) { + this.tempHC = new _Tensor.default([], [dimCandidate]); + this.tempHC.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.previousCandidate || !this.stateful) { + this.previousCandidate = new _Tensor.default([], [dimCandidate]); + this.previousCandidate.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new _Tensor.default([], [dimCandidate]); + this.currentHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.previousHiddenState) { + this.previousHiddenState = new _Tensor.default([], [dimCandidate]); + this.previousHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new _Tensor.default([], [x.glTextureShape[0], dimCandidate]); + this.hiddenStateSequence.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new _Tensor.default([], [x.glTextureShape[0], dimCandidate]); + this.hiddenStateSequenceCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentX) { + this.currentX = new _Tensor.default([], [x.glTextureShape[1]]); + this.currentX.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _WebGL.webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: inputIndex, + type: 'int', + name: 'index' + }] + }); + + this._stepGPU(); + + if (this.returnSequences) { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ + input: this.hiddenStateSequence, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ + input: this.currentHiddenState, + name: 'x' + }, { + input: this.hiddenStateSequenceCopy, + name: 'y' + }], + uniforms: [{ + value: i, + type: 'int', + name: 'index' + }] + }); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = this.currentHiddenState; + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = LSTM; \ No newline at end of file diff --git a/keras-js/lib/layers/recurrent/SimpleRNN.js b/keras-js/lib/layers/recurrent/SimpleRNN.js new file mode 100644 index 0000000000..d8f3060b6e --- /dev/null +++ b/keras-js/lib/layers/recurrent/SimpleRNN.js @@ -0,0 +1,355 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var activations = _interopRequireWildcard(require("../../activations")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _cwise = _interopRequireDefault(require("cwise")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; +const gateSummationProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nuniform sampler2D bias;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(bias, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n float bias_val = texelFetch(bias, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val + t2_val + bias_val);\r\n}\r\n"; +const timestepReadProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n\r\n outColor = vec4(texelFetch(x, ivec2(out_x, index), 0).r);\r\n}\r\n"; +const timestepWriteProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D y;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(y, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (out_y == index) {\r\n outColor = vec4(texelFetch(x, ivec2(out_x, 0), 0).r);\r\n } else {\r\n outColor = vec4(texelFetch(y, ivec2(out_x, out_y), 0).r);\r\n }\r\n}\r\n"; + +class SimpleRNN extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + Object.defineProperty(this, "_combine", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array', 'array'], + body: function (_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b; + } + }) + }); + this.layerClass = 'SimpleRNN'; + const { + units = 1, + activation = 'tanh', + use_bias = true, + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs; + this.units = units; + this.activation = activation; + this.activationFunc = activations[activation]; + this.use_bias = use_bias; + this.returnSequences = return_sequences; + this.goBackwards = go_backwards; + this.stateful = stateful; + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel']; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + this.gateSummationProgram = _WebGL.webgl2.compileProgram(gateSummationProgramSource); + this.timestepReadProgram = _WebGL.webgl2.compileProgram(timestepReadProgramSource); + this.timestepWriteProgram = _WebGL.webgl2.compileProgram(timestepWriteProgramSource); + } + } + + setWeights(weightsArr) { + super.setWeights(weightsArr); + + if (!this.use_bias) { + this.weights['bias'] = new _Tensor.default([], [this.units]); + + if (this.gpu) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const dimHiddenState = this.units; + const currentHiddenState = this.stateful && this.currentHiddenState ? this.currentHiddenState : new _Tensor.default([], [dimHiddenState]); + const tempXH = new _Tensor.default([], [dimHiddenState]); + const tempHH = new _Tensor.default([], [dimHiddenState]); + const previousHiddenState = new _Tensor.default([], [dimHiddenState]); + this.hiddenStateSequence = new _Tensor.default([], [x.tensor.shape[0], dimHiddenState]); + const currentX = new _Tensor.default([], [x.tensor.shape[1]]); + + const _step = () => { + _ndarrayOps.default.assign(previousHiddenState.tensor, currentHiddenState.tensor); + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['kernel'].tensor.transpose(1, 0), currentX.tensor, 1, tempXH.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['recurrent_kernel'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHH.tensor); + + this._combine(currentHiddenState.tensor, tempXH.tensor, tempHH.tensor, this.weights['bias'].tensor); + + this.activationFunc(currentHiddenState); + }; + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _ndarrayOps.default.assign(currentX.tensor, x.tensor.pick(inputIndex, null)); + + const tempTensors = [tempXH, tempHH]; + tempTensors.forEach(temp => _ndarrayOps.default.assigns(temp.tensor, 0)); + + _step(); + + if (this.returnSequences) { + _ndarrayOps.default.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = currentHiddenState; + } + + if (this.stateful) { + this.currentHiddenState = currentHiddenState; + } + } + + _stepGPU() { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ + input: this.currentHiddenState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXH, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHH, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['recurrent_kernel'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentHiddenStatePreactiv, + inputs: [{ + input: this.tempXH, + name: 't1' + }, { + input: this.tempHH, + name: 't2' + }, { + input: this.weights['bias'], + name: 'bias' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.currentHiddenState, + inputs: [{ + input: this.currentHiddenStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentHiddenState = this.currentHiddenStatePreactiv; + } + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const dimHiddenState = this.units; + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentHiddenStatePreactiv) { + this.currentHiddenStatePreactiv = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXH) { + this.tempXH = new _Tensor.default([], [dimHiddenState]); + this.tempXH.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHH) { + this.tempHH = new _Tensor.default([], [dimHiddenState]); + this.tempHH.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.previousHiddenState) { + this.previousHiddenState = new _Tensor.default([], [dimHiddenState]); + this.previousHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new _Tensor.default([], [x.glTextureShape[0], dimHiddenState]); + this.hiddenStateSequence.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new _Tensor.default([], [x.glTextureShape[0], dimHiddenState]); + this.hiddenStateSequenceCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentX) { + this.currentX = new _Tensor.default([], [x.glTextureShape[1]]); + this.currentX.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _WebGL.webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: inputIndex, + type: 'int', + name: 'index' + }] + }); + + this._stepGPU(); + + if (this.returnSequences) { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ + input: this.hiddenStateSequence, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ + input: this.currentHiddenState, + name: 'x' + }, { + input: this.hiddenStateSequenceCopy, + name: 'y' + }], + uniforms: [{ + value: i, + type: 'int', + name: 'index' + }] + }); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = this.currentHiddenState; + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = SimpleRNN; \ No newline at end of file diff --git a/keras-js/lib/layers/recurrent/index.js b/keras-js/lib/layers/recurrent/index.js new file mode 100644 index 0000000000..d5f72ef7fb --- /dev/null +++ b/keras-js/lib/layers/recurrent/index.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "SimpleRNN", { + enumerable: true, + get: function () { + return _SimpleRNN.default; + } +}); +Object.defineProperty(exports, "LSTM", { + enumerable: true, + get: function () { + return _LSTM.default; + } +}); +Object.defineProperty(exports, "GRU", { + enumerable: true, + get: function () { + return _GRU.default; + } +}); + +var _SimpleRNN = _interopRequireDefault(require("./SimpleRNN")); + +var _LSTM = _interopRequireDefault(require("./LSTM")); + +var _GRU = _interopRequireDefault(require("./GRU")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/layers/wrappers/Bidirectional.js b/keras-js/lib/layers/wrappers/Bidirectional.js new file mode 100644 index 0000000000..736ca2e452 --- /dev/null +++ b/keras-js/lib/layers/wrappers/Bidirectional.js @@ -0,0 +1,210 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var recurrentLayers = _interopRequireWildcard(require("../recurrent")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const concatMergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D forward;\r\nuniform sampler2D backward;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(forward, 0);\r\n int out_x = int(float(size[0] * 2) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (out_x >= 0 && out_x < size[0]) {\r\n outColor = vec4(texelFetch(forward, ivec2(out_x, out_y), 0).r);\r\n } else {\r\n outColor = vec4(texelFetch(backward, ivec2(out_x - size[0], size[1] - out_y - 1), 0).r);\r\n }\r\n}\r\n"; +const sumMergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D forward;\r\nuniform sampler2D backward;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(forward, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r;\r\n float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r;\r\n\r\n outColor = vec4(forward_val + backward_val);\r\n}\r\n"; +const mulMergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D forward;\r\nuniform sampler2D backward;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(forward, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r;\r\n float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r;\r\n\r\n outColor = vec4(forward_val * backward_val);\r\n}\r\n"; +const aveMergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D forward;\r\nuniform sampler2D backward;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(forward, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r;\r\n float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r;\r\n\r\n outColor = vec4(0.5 * (forward_val + backward_val));\r\n}\r\n"; + +class Bidirectional extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Bidirectional'; + const { + layer, + merge_mode = 'concat' + } = attrs; + + if (!layer) { + this.throwError('wrapped layer is undefined.'); + } + + if (!['SimpleRNN', 'GRU', 'LSTM'].includes(layer.class_name)) { + this.throwError(`cannot wrap ${layer.class_name} layer.`); + } + + if (!['concat', 'sum', 'mul', 'ave'].includes(merge_mode)) { + this.throwError(`merge_mode ${merge_mode} not supported.`); + } + + const forwardLayerAttrs = Object.assign({}, layer.config, { + gpu: attrs.gpu + }); + const backwardLayerAttrs = Object.assign({}, layer.config, { + gpu: attrs.gpu + }); + backwardLayerAttrs.go_backwards = !backwardLayerAttrs.go_backwards; + this.forwardLayer = new recurrentLayers[layer.class_name](forwardLayerAttrs); + this.backwardLayer = new recurrentLayers[layer.class_name](backwardLayerAttrs); + this.forwardLayer.outbound = [null]; + this.backwardLayer.outbound = [null]; + this.mergeMode = merge_mode; + this.returnSequences = layer.config.return_sequences; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + + if (this.mergeMode === 'concat') { + this.mergeProgram = _WebGL.webgl2.compileProgram(concatMergeProgramSource); + } else if (this.mergeMode === 'sum') { + this.mergeProgram = _WebGL.webgl2.compileProgram(sumMergeProgramSource); + } else if (this.mergeMode === 'mul') { + this.mergeProgram = _WebGL.webgl2.compileProgram(mulMergeProgramSource); + } else if (this.mergeMode === 'ave') { + this.mergeProgram = _WebGL.webgl2.compileProgram(aveMergeProgramSource); + } + } + } + + setWeights(weightsArr) { + this.forwardLayer.setWeights(weightsArr.slice(0, weightsArr.length / 2)); + this.backwardLayer.setWeights(weightsArr.slice(weightsArr.length / 2)); + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.forwardLayer._callCPU(new _Tensor.default(x.tensor.data, x.tensor.shape)); + + this.backwardLayer._callCPU(new _Tensor.default(x.tensor.data, x.tensor.shape)); + + const forwardOutput = this.forwardLayer.output; + const backwardOutput = this.backwardLayer.output; + + if (this.returnSequences) { + backwardOutput.tensor = backwardOutput.tensor.step(-1); + } + + const outShape = forwardOutput.tensor.shape.slice(); + + if (this.mergeMode === 'concat') { + outShape[outShape.length - 1] += backwardOutput.tensor.shape[outShape.length - 1]; + } + + this.output = new _Tensor.default([], outShape); + + if (this.mergeMode === 'concat') { + if (this.returnSequences) { + _ndarrayOps.default.assign(this.output.tensor.hi(outShape[0], forwardOutput.tensor.shape[1]).lo(0, 0), forwardOutput.tensor); + + _ndarrayOps.default.assign(this.output.tensor.hi(outShape[0], outShape[1]).lo(0, forwardOutput.tensor.shape[1]), backwardOutput.tensor); + } else { + _ndarrayOps.default.assign(this.output.tensor.hi(forwardOutput.tensor.shape[0]).lo(0), forwardOutput.tensor); + + _ndarrayOps.default.assign(this.output.tensor.hi(outShape[0]).lo(forwardOutput.tensor.shape[0]), backwardOutput.tensor); + } + } else if (this.mergeMode === 'sum') { + _ndarrayOps.default.addeq(this.output.tensor, forwardOutput.tensor); + + _ndarrayOps.default.addeq(this.output.tensor, backwardOutput.tensor); + } else if (this.mergeMode === 'mul') { + _ndarrayOps.default.assigns(this.output.tensor, 1); + + _ndarrayOps.default.muleq(this.output.tensor, forwardOutput.tensor); + + _ndarrayOps.default.muleq(this.output.tensor, backwardOutput.tensor); + } else if (this.mergeMode === 'ave') { + _ndarrayOps.default.addeq(this.output.tensor, forwardOutput.tensor); + + _ndarrayOps.default.addeq(this.output.tensor, backwardOutput.tensor); + + _ndarrayOps.default.divseq(this.output.tensor, 2); + } + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.inputCopy) { + this.inputCopy = new _Tensor.default([], x.glTextureShape); + this.inputCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.inputCopy, + inputs: [{ + input: x, + name: 'source' + }] + }); + + this.forwardLayer._callGPU(x); + + this.backwardLayer._callGPU(this.inputCopy); + + const forwardOutput = this.forwardLayer.output; + const backwardOutput = this.backwardLayer.output; + const outShape = forwardOutput.glTextureShape.slice(); + + if (this.mergeMode === 'concat') { + outShape[1] += backwardOutput.glTextureShape[1]; + } + + if (!this.output) { + this.output = new _Tensor.default([], outShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + + if (!this.returnSequences) { + this.output.is1D = true; + } + } + + _WebGL.webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: [{ + input: forwardOutput, + name: 'forward' + }, { + input: backwardOutput, + name: 'backward' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Bidirectional; \ No newline at end of file diff --git a/keras-js/lib/layers/wrappers/TimeDistributed.js b/keras-js/lib/layers/wrappers/TimeDistributed.js new file mode 100644 index 0000000000..842ffa9993 --- /dev/null +++ b/keras-js/lib/layers/wrappers/TimeDistributed.js @@ -0,0 +1,409 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var layers = _interopRequireWildcard(require("../")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const selectSliceProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int t;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n\r\n outColor = vec4(texelFetch(x, ivec2(out_x, t), 0).r);\r\n}\r\n"; +const copySliceOutputProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D outputCopy;\r\nuniform sampler2D sliceOutput;\r\nuniform int t;\r\nuniform int timesteps;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(sliceOutput, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(timesteps) * outTex.y);\r\n\r\n if (t == out_y) {\r\n outColor = vec4(texelFetch(sliceOutput, ivec2(out_x, 0), 0).r);\r\n } else {\r\n outColor = texelFetch(outputCopy, ivec2(out_x, out_y), 0);\r\n }\r\n}\r\n"; +const mapSliceOutputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D outputCopy;\r\nuniform sampler2D sliceOutput;\r\nuniform isampler2D indexMap;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(outputCopy, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(textureSize(sliceOutput, 0)[0])));\r\n int colIndex = int(mod(float(index), float(textureSize(sliceOutput, 0)[0])));\r\n float val = texelFetch(sliceOutput, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = texelFetch(outputCopy, ivec2(out_x, out_y), 0);\r\n }\r\n}\r\n"; + +class TimeDistributed extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'TimeDistributed'; + const { + layer + } = attrs; + + if (!layer) { + this.throwError('wrapped layer is undefined.'); + } + + const wrappedLayerAttrs = Object.assign({}, layer.config, { + gpu: attrs.gpu + }); + this.wrappedLayer = new layers[layer.class_name](wrappedLayerAttrs); + this.wrappedLayer.outbound = [null]; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + this.selectSliceProgram = _WebGL.webgl2.compileProgram(selectSliceProgramSource); + this.copySliceOutputProgram = _WebGL.webgl2.compileProgram(copySliceOutputProgramSource); + this.mapSliceOutputProgram = _WebGL.webgl2.compileProgram(mapSliceOutputProgramSource); + } + } + + setWeights(weightsArr) { + this.wrappedLayer.setWeights(weightsArr); + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const stepShape = [...x.tensor.shape.slice(1)]; + const step = new _Tensor.default([], stepShape); + + _ndarrayOps.default.assign(step.tensor, x.tensor.pick(0, ...Array(stepShape.length).fill(null))); + + let stepOutput = this.wrappedLayer.call(step); + const stepOutputShape = stepOutput.tensor.shape.slice(); + this.output = new _Tensor.default([], [x.tensor.shape[0], ...stepOutputShape]); + + _ndarrayOps.default.assign(this.output.tensor.pick(0, ...Array(stepOutputShape.length).fill(null)), stepOutput.tensor); + + for (let i = 1, timesteps = x.tensor.shape[0]; i < timesteps; i++) { + _ndarrayOps.default.assign(step.tensor, x.tensor.pick(i, ...Array(stepShape.length).fill(null))); + + stepOutput = this.wrappedLayer.call(step); + + _ndarrayOps.default.assign(this.output.tensor.pick(i, ...Array(stepOutputShape.length).fill(null)), stepOutput.tensor); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMaps) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMaps = []; + const timesteps = this.inputShape[0]; + const sliceShape = this.inputShape.slice(1); + + for (let t = 0; t < timesteps; t++) { + const sliceIndices = new _Tensor.default([], sliceShape, { + type: Int32Array + }); + + _ndarrayOps.default.assign(sliceIndices.tensor, indices.tensor.pick(t, ...Array(sliceShape.length).fill(null))); + + sliceIndices.reshapeTo2DSquare(); + sliceIndices.createGLTexture({ + type: '2d', + format: 'int' + }); + this.indexMaps.push(sliceIndices); + } + } + + _createOutputIndexMap(indicesForReshaped) { + if (this.outputIndexMaps) { + return; + } + + const outputSliceIndices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.outputIndexMaps = []; + const timesteps = this.outputShape[0]; + const sliceShape = this.outputShape.slice(1); + + for (let t = 0; t < timesteps; t++) { + const outputIndices = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + + _ndarrayOps.default.assigns(outputIndices.tensor, -1); + + _ndarrayOps.default.assign(outputIndices.tensor.pick(t, ...Array(sliceShape.length).fill(null)), outputSliceIndices.tensor); + + outputIndices.reshapeTo2DSquare(); + outputIndices.createGLTexture({ + type: '2d', + format: 'int' + }); + this.outputIndexMaps.push(outputIndices); + } + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + + if (!x.glTexture) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + + if (this.inputShape.length > 2) { + this._createIndexMap(x.indicesForReshaped); + } + + const timesteps = this.inputShape[0]; + const sliceShape = this.inputShape.slice(1); + + if (!this.slice) { + this.slice = new _Tensor.default([], sliceShape); + + if (sliceShape.length <= 2) { + this.slice.createGLTexture({ + type: '2d', + format: 'float' + }); + } else { + this.slice.reshapeTo2DSquare(); + this.slice.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + + if (this.inputShape.length <= 2) { + _WebGL.webgl2.runProgram({ + program: this.selectSliceProgram, + output: this.slice, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: 0, + type: 'int', + name: 't' + }] + }); + } else { + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.slice, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMaps[0], + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + } + + this.wrappedLayer._callGPU(this.slice); + + this.sliceOutput = this.wrappedLayer.output; + + if (!this.output) { + if (this.inputShape.length <= 2) { + this.outputShape = [timesteps, this.sliceOutput.glTextureShape[1]]; + this.output = new _Tensor.default([], this.outputShape); + this.outputCopy = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + this.outputCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } else { + this.outputShape = [timesteps, ...this.sliceOutput.originalShape]; + this.output = new _Tensor.default([], this.outputShape); + this.outputCopy = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.outputCopy.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + this.outputCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + + this._createOutputIndexMap(this.sliceOutput.indicesForReshaped); + } + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.outputCopy, + inputs: [{ + input: this.output, + name: 'source' + }] + }); + + if (this.inputShape.length <= 2) { + _WebGL.webgl2.runProgram({ + program: this.copySliceOutputProgram, + output: this.output, + inputs: [{ + input: this.outputCopy, + name: 'outputCopy' + }, { + input: this.sliceOutput, + name: 'sliceOutput' + }], + uniforms: [{ + value: 0, + type: 'int', + name: 't' + }, { + value: timesteps, + type: 'int', + name: 'timesteps' + }] + }); + } else { + _WebGL.webgl2.runProgram({ + program: this.mapSliceOutputProgram, + output: this.output, + inputs: [{ + input: this.outputCopy, + name: 'outputCopy' + }, { + input: this.sliceOutput, + name: 'sliceOutput' + }, { + input: this.outputIndexMaps[0], + name: 'indexMap' + }] + }); + } + + for (let i = 1; i < timesteps; i++) { + if (this.inputShape.length <= 2) { + _WebGL.webgl2.runProgram({ + program: this.selectSliceProgram, + output: this.slice, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: i, + type: 'int', + name: 't' + }] + }); + } else { + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.slice, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMaps[i], + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + } + + this.wrappedLayer._callGPU(this.slice); + + this.sliceOutput = this.wrappedLayer.output; + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.outputCopy, + inputs: [{ + input: this.output, + name: 'source' + }] + }); + + if (this.inputShape.length <= 2) { + _WebGL.webgl2.runProgram({ + program: this.copySliceOutputProgram, + output: this.output, + inputs: [{ + input: this.outputCopy, + name: 'outputCopy' + }, { + input: this.sliceOutput, + name: 'sliceOutput' + }], + uniforms: [{ + value: i, + type: 'int', + name: 't' + }, { + value: timesteps, + type: 'int', + name: 'timesteps' + }] + }); + } else { + _WebGL.webgl2.runProgram({ + program: this.mapSliceOutputProgram, + output: this.output, + inputs: [{ + input: this.outputCopy, + name: 'outputCopy' + }, { + input: this.sliceOutput, + name: 'sliceOutput' + }, { + input: this.outputIndexMaps[i], + name: 'indexMap' + }] + }); + } + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = TimeDistributed; \ No newline at end of file diff --git a/keras-js/lib/layers/wrappers/index.js b/keras-js/lib/layers/wrappers/index.js new file mode 100644 index 0000000000..48c31cf75e --- /dev/null +++ b/keras-js/lib/layers/wrappers/index.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "TimeDistributed", { + enumerable: true, + get: function () { + return _TimeDistributed.default; + } +}); +Object.defineProperty(exports, "Bidirectional", { + enumerable: true, + get: function () { + return _Bidirectional.default; + } +}); + +var _TimeDistributed = _interopRequireDefault(require("./TimeDistributed")); + +var _Bidirectional = _interopRequireDefault(require("./Bidirectional")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/proto.js b/keras-js/lib/proto.js new file mode 100644 index 0000000000..7ea63640c3 --- /dev/null +++ b/keras-js/lib/proto.js @@ -0,0 +1,352 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.Model = exports.Weights = void 0; + +var $protobuf = _interopRequireWildcard(require("protobufjs/minimal")); + +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; } } + +const $Reader = $protobuf.Reader, + $Writer = $protobuf.Writer, + $util = $protobuf.util; +const $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); +exports.default = $root; + +const Weights = $root.Weights = (() => { + function Weights(properties) { + this.shape = []; + if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + Weights.prototype.layerName = ""; + Weights.prototype.weightName = ""; + Weights.prototype.shape = $util.emptyArray; + Weights.prototype.type = ""; + Weights.prototype.data = $util.newBuffer([]); + Weights.prototype.quantizeMin = 0; + Weights.prototype.quantizeMax = 0; + + Weights.create = function create(properties) { + return new Weights(properties); + }; + + Weights.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.layerName != null && message.hasOwnProperty("layerName")) writer.uint32(10).string(message.layerName); + if (message.weightName != null && message.hasOwnProperty("weightName")) writer.uint32(18).string(message.weightName); + + if (message.shape != null && message.shape.length) { + writer.uint32(26).fork(); + + for (let i = 0; i < message.shape.length; ++i) writer.uint32(message.shape[i]); + + writer.ldelim(); + } + + if (message.type != null && message.hasOwnProperty("type")) writer.uint32(34).string(message.type); + if (message.data != null && message.hasOwnProperty("data")) writer.uint32(42).bytes(message.data); + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) writer.uint32(53).float(message.quantizeMin); + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) writer.uint32(61).float(message.quantizeMax); + return writer; + }; + + Weights.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + Weights.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.Weights(); + + while (reader.pos < end) { + let tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.layerName = reader.string(); + break; + + case 2: + message.weightName = reader.string(); + break; + + case 3: + if (!(message.shape && message.shape.length)) message.shape = []; + + if ((tag & 7) === 2) { + let end2 = reader.uint32() + reader.pos; + + while (reader.pos < end2) message.shape.push(reader.uint32()); + } else message.shape.push(reader.uint32()); + + break; + + case 4: + message.type = reader.string(); + break; + + case 5: + message.data = reader.bytes(); + break; + + case 6: + message.quantizeMin = reader.float(); + break; + + case 7: + message.quantizeMax = reader.float(); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }; + + Weights.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + Weights.verify = function verify(message) { + if (typeof message !== "object" || message === null) return "object expected"; + if (message.layerName != null && message.hasOwnProperty("layerName")) if (!$util.isString(message.layerName)) return "layerName: string expected"; + if (message.weightName != null && message.hasOwnProperty("weightName")) if (!$util.isString(message.weightName)) return "weightName: string expected"; + + if (message.shape != null && message.hasOwnProperty("shape")) { + if (!Array.isArray(message.shape)) return "shape: array expected"; + + for (let i = 0; i < message.shape.length; ++i) if (!$util.isInteger(message.shape[i])) return "shape: integer[] expected"; + } + + if (message.type != null && message.hasOwnProperty("type")) if (!$util.isString(message.type)) return "type: string expected"; + if (message.data != null && message.hasOwnProperty("data")) if (!(message.data && typeof message.data.length === "number" || $util.isString(message.data))) return "data: buffer expected"; + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) if (typeof message.quantizeMin !== "number") return "quantizeMin: number expected"; + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) if (typeof message.quantizeMax !== "number") return "quantizeMax: number expected"; + return null; + }; + + Weights.fromObject = function fromObject(object) { + if (object instanceof $root.Weights) return object; + let message = new $root.Weights(); + if (object.layerName != null) message.layerName = String(object.layerName); + if (object.weightName != null) message.weightName = String(object.weightName); + + if (object.shape) { + if (!Array.isArray(object.shape)) throw TypeError(".Weights.shape: array expected"); + message.shape = []; + + for (let i = 0; i < object.shape.length; ++i) message.shape[i] = object.shape[i] >>> 0; + } + + if (object.type != null) message.type = String(object.type); + if (object.data != null) if (typeof object.data === "string") $util.base64.decode(object.data, message.data = $util.newBuffer($util.base64.length(object.data)), 0);else if (object.data.length) message.data = object.data; + if (object.quantizeMin != null) message.quantizeMin = Number(object.quantizeMin); + if (object.quantizeMax != null) message.quantizeMax = Number(object.quantizeMax); + return message; + }; + + Weights.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.shape = []; + + if (options.defaults) { + object.layerName = ""; + object.weightName = ""; + object.type = ""; + object.data = options.bytes === String ? "" : []; + object.quantizeMin = 0; + object.quantizeMax = 0; + } + + if (message.layerName != null && message.hasOwnProperty("layerName")) object.layerName = message.layerName; + if (message.weightName != null && message.hasOwnProperty("weightName")) object.weightName = message.weightName; + + if (message.shape && message.shape.length) { + object.shape = []; + + for (let j = 0; j < message.shape.length; ++j) object.shape[j] = message.shape[j]; + } + + if (message.type != null && message.hasOwnProperty("type")) object.type = message.type; + if (message.data != null && message.hasOwnProperty("data")) object.data = options.bytes === String ? $util.base64.encode(message.data, 0, message.data.length) : options.bytes === Array ? Array.prototype.slice.call(message.data) : message.data; + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) object.quantizeMin = options.json && !isFinite(message.quantizeMin) ? String(message.quantizeMin) : message.quantizeMin; + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) object.quantizeMax = options.json && !isFinite(message.quantizeMax) ? String(message.quantizeMax) : message.quantizeMax; + return object; + }; + + Weights.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Weights; +})(); + +exports.Weights = Weights; + +const Model = $root.Model = (() => { + function Model(properties) { + this.modelWeights = []; + if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + Model.prototype.id = ""; + Model.prototype.name = ""; + Model.prototype.kerasVersion = ""; + Model.prototype.backend = ""; + Model.prototype.modelConfig = ""; + Model.prototype.modelWeights = $util.emptyArray; + + Model.create = function create(properties) { + return new Model(properties); + }; + + Model.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.id != null && message.hasOwnProperty("id")) writer.uint32(10).string(message.id); + if (message.name != null && message.hasOwnProperty("name")) writer.uint32(18).string(message.name); + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) writer.uint32(26).string(message.kerasVersion); + if (message.backend != null && message.hasOwnProperty("backend")) writer.uint32(34).string(message.backend); + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) writer.uint32(42).string(message.modelConfig); + if (message.modelWeights != null && message.modelWeights.length) for (let i = 0; i < message.modelWeights.length; ++i) $root.Weights.encode(message.modelWeights[i], writer.uint32(50).fork()).ldelim(); + return writer; + }; + + Model.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + Model.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.Model(); + + while (reader.pos < end) { + let tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.id = reader.string(); + break; + + case 2: + message.name = reader.string(); + break; + + case 3: + message.kerasVersion = reader.string(); + break; + + case 4: + message.backend = reader.string(); + break; + + case 5: + message.modelConfig = reader.string(); + break; + + case 6: + if (!(message.modelWeights && message.modelWeights.length)) message.modelWeights = []; + message.modelWeights.push($root.Weights.decode(reader, reader.uint32())); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }; + + Model.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + Model.verify = function verify(message) { + if (typeof message !== "object" || message === null) return "object expected"; + if (message.id != null && message.hasOwnProperty("id")) if (!$util.isString(message.id)) return "id: string expected"; + if (message.name != null && message.hasOwnProperty("name")) if (!$util.isString(message.name)) return "name: string expected"; + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) if (!$util.isString(message.kerasVersion)) return "kerasVersion: string expected"; + if (message.backend != null && message.hasOwnProperty("backend")) if (!$util.isString(message.backend)) return "backend: string expected"; + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) if (!$util.isString(message.modelConfig)) return "modelConfig: string expected"; + + if (message.modelWeights != null && message.hasOwnProperty("modelWeights")) { + if (!Array.isArray(message.modelWeights)) return "modelWeights: array expected"; + + for (let i = 0; i < message.modelWeights.length; ++i) { + let error = $root.Weights.verify(message.modelWeights[i]); + if (error) return "modelWeights." + error; + } + } + + return null; + }; + + Model.fromObject = function fromObject(object) { + if (object instanceof $root.Model) return object; + let message = new $root.Model(); + if (object.id != null) message.id = String(object.id); + if (object.name != null) message.name = String(object.name); + if (object.kerasVersion != null) message.kerasVersion = String(object.kerasVersion); + if (object.backend != null) message.backend = String(object.backend); + if (object.modelConfig != null) message.modelConfig = String(object.modelConfig); + + if (object.modelWeights) { + if (!Array.isArray(object.modelWeights)) throw TypeError(".Model.modelWeights: array expected"); + message.modelWeights = []; + + for (let i = 0; i < object.modelWeights.length; ++i) { + if (typeof object.modelWeights[i] !== "object") throw TypeError(".Model.modelWeights: object expected"); + message.modelWeights[i] = $root.Weights.fromObject(object.modelWeights[i]); + } + } + + return message; + }; + + Model.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.modelWeights = []; + + if (options.defaults) { + object.id = ""; + object.name = ""; + object.kerasVersion = ""; + object.backend = ""; + object.modelConfig = ""; + } + + if (message.id != null && message.hasOwnProperty("id")) object.id = message.id; + if (message.name != null && message.hasOwnProperty("name")) object.name = message.name; + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) object.kerasVersion = message.kerasVersion; + if (message.backend != null && message.hasOwnProperty("backend")) object.backend = message.backend; + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) object.modelConfig = message.modelConfig; + + if (message.modelWeights && message.modelWeights.length) { + object.modelWeights = []; + + for (let j = 0; j < message.modelWeights.length; ++j) object.modelWeights[j] = $root.Weights.toObject(message.modelWeights[j], options); + } + + return object; + }; + + Model.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Model; +})(); + +exports.Model = Model; \ No newline at end of file diff --git a/keras-js/lib/utils/tensorUtils.js b/keras-js/lib/utils/tensorUtils.js new file mode 100644 index 0000000000..b2d81ffb1b --- /dev/null +++ b/keras-js/lib/utils/tensorUtils.js @@ -0,0 +1,89 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.checkShape = checkShape; +exports.data3DLayoutForGL = data3DLayoutForGL; +exports.createIndicesFor2DReshaped = createIndicesFor2DReshaped; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +var _ndarray = _interopRequireDefault(require("ndarray")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function checkShape(data, shape) { + if (data.length && shape.length && data.length !== shape.reduce((a, b) => a * b, 1)) { + throw new Error('[Tensor] specified shape incompatible with data.'); + } +} + +function data3DLayoutForGL(typedarrayConstructor, arr, shape) { + const data = new typedarrayConstructor(arr.data.length); + const slice = (0, _ndarray.default)(new typedarrayConstructor(shape[0] * shape[1]), [shape[0], shape[1]]); + let offset = 0; + + for (let i = 0; i < shape[2]; i++) { + _ndarrayOps.default.assign(slice, arr.pick(null, null, i)); + + data.set(slice.data, offset); + offset += shape[0] * shape[1]; + } + + return data; +} + +function createIndicesFor2DReshaped(shape, square = false, axis = -1) { + const size = shape.reduce((a, b) => a * b, 1); + const indicesArr = (0, _ndarray.default)(new Int32Array(size), shape); + + if (square) { + const squareDim = Math.ceil(Math.sqrt(size)); + const indicesRowArrReshaped = (0, _ndarray.default)(new Int32Array(squareDim ** 2), [squareDim, squareDim]); + const indicesColArrReshaped = (0, _ndarray.default)(new Int32Array(squareDim ** 2), [squareDim, squareDim]); + const indicesArrReshaped = (0, _ndarray.default)(new Int32Array(squareDim ** 2), [squareDim, squareDim]); + + for (let i = 0; i < squareDim; i++) { + _ndarrayOps.default.assigns(indicesRowArrReshaped.pick(i, null), i); + } + + for (let j = 0; j < squareDim; j++) { + _ndarrayOps.default.assigns(indicesColArrReshaped.pick(null, j), j); + } + + _ndarrayOps.default.muls(indicesArrReshaped, indicesRowArrReshaped, squareDim); + + _ndarrayOps.default.addeq(indicesArrReshaped, indicesColArrReshaped); + + indicesArr.data.set(indicesArrReshaped.data.subarray(0, indicesArr.size)); + } else { + if (axis < 0) { + axis = shape.length + axis; + } + + const axisSize = shape[axis]; + const indicesRowArr = (0, _ndarray.default)(new Int32Array(size), shape); + const indicesColArr = (0, _ndarray.default)(new Int32Array(size), shape); + const otherAxes = [...shape.slice(0, axis), ...shape.slice(axis + 1)]; + const otherAxesSize = otherAxes.reduce((a, b) => a * b, 1); + const indicesRowArrSlice = (0, _ndarray.default)(new Int32Array((0, _range2.default)(otherAxesSize)), otherAxes); + const axisSlices = Array(shape.length).fill(null); + + for (let n = 0; n < axisSize; n++) { + axisSlices[axis] = n; + + _ndarrayOps.default.assign(indicesRowArr.pick(...axisSlices), indicesRowArrSlice); + + _ndarrayOps.default.assigns(indicesColArr.pick(...axisSlices), n); + } + + _ndarrayOps.default.muls(indicesArr, indicesRowArr, axisSize); + + _ndarrayOps.default.addeq(indicesArr, indicesColArr); + } + + return indicesArr; +} \ No newline at end of file diff --git a/keras-js/lib/utils/testUtils.js b/keras-js/lib/utils/testUtils.js new file mode 100644 index 0000000000..36e30b5d69 --- /dev/null +++ b/keras-js/lib/utils/testUtils.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.approxEquals = approxEquals; + +var _isFinite2 = _interopRequireDefault(require("lodash/isFinite")); + +var _flattenDeep2 = _interopRequireDefault(require("lodash/flattenDeep")); + +var _ndarrayUnpack = _interopRequireDefault(require("ndarray-unpack")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function approxEquals(ndarrayOut, dataExpected, tol = 0.0001) { + const a = (0, _flattenDeep2.default)((0, _ndarrayUnpack.default)(ndarrayOut)); + const b = dataExpected; + + if (a.length !== b.length) { + return false; + } + + for (let i = 0; i < a.length; i++) { + if (!(0, _isFinite2.default)(a[i])) { + return false; + } + + if (a[i] < b[i] - tol || a[i] > b[i] + tol) { + return false; + } + } + + return true; +} \ No newline at end of file diff --git a/keras-js/lib/visualizations/CAM.js b/keras-js/lib/visualizations/CAM.js new file mode 100644 index 0000000000..893ea2f6aa --- /dev/null +++ b/keras-js/lib/visualizations/CAM.js @@ -0,0 +1,172 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Tensor = _interopRequireDefault(require("../Tensor")); + +var _WebGL = require("../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var _createGLSLProgram = _interopRequireDefault(require("../webgl/dynamic/createGLSLProgram")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class CAM { + constructor(attrs = {}) { + this.modelLayersMap = attrs.modelLayersMap; + this.gpu = attrs.gpu; + + if (!this.modelLayersMap) { + throw new Error(`[CAM] modelLayersMap is required`); + } + } + + initialize() { + this.modelLayersMap.forEach(layer => { + if (layer.layerClass === 'GlobalAveragePooling2D') { + this.enabled = true; + this.poolLayer = layer; + } + }); + + if (this.enabled && !this.data) { + this.featureMaps = this.modelLayersMap.get(this.poolLayer.inbound[0]).output; + let weightsFound = false; + let finalLayerReached = false; + let traversingLayer = this.poolLayer; + + while (!weightsFound && !finalLayerReached) { + traversingLayer = this.modelLayersMap.get(traversingLayer.outbound[0]); + + if (traversingLayer.weights['kernel']) { + this.weights = traversingLayer.weights['kernel']; + weightsFound = true; + } else if (!traversingLayer.outbound.length) { + this.weights = this.poolLayer.output; + finalLayerReached = true; + } + } + + if (this.featureMaps.is2DReshaped) { + this.inputShape = this.featureMaps.originalShape.slice(0, 2); + } else { + this.inputShape = this.featureMaps.tensor.shape.slice(0, 2); + } + + if (this.weights.tensor.shape.length === 1) { + this.shape = this.inputShape; + } else { + const numOutputClasses = this.weights.tensor.shape[1]; + this.shape = [...this.inputShape, numOutputClasses]; + } + + this.data = new Float32Array(this.shape.reduce((a, b) => a * b, 1)); + } + } + + update() { + if (!this.enabled) return; + this.featureMaps = this.modelLayersMap.get(this.poolLayer.inbound[0]).output; + + if (this.gpu) { + this._updateGPU(); + } else { + this._updateCPU(); + } + + const outputMin = _ndarrayOps.default.inf(this.output.tensor); + + const outputMax = _ndarrayOps.default.sup(this.output.tensor); + + _ndarrayOps.default.divseq(_ndarrayOps.default.subseq(this.output.tensor, outputMin), outputMax - outputMin); + + this.data = this.output.tensor.data; + } + + _updateCPU() { + if (!this.featureMaps.is2DReshaped) { + this.featureMaps.reshapeTo2D(); + } + + if (this.weights.tensor.shape.length === 1) { + if (!this.output) { + this.output = new _Tensor.default([], this.shape); + } + + const matVec = new _Tensor.default([], [this.shape[0] * this.shape[1]]); + (0, _ndarrayBlasLevel.gemv)(1, this.featureMaps.tensor, this.weights.tensor, 1, matVec.tensor); + this.output.replaceTensorData(matVec.tensor.data); + } else { + if (!this.output) { + this.output = new _Tensor.default([], this.shape); + } + + this.output.reshapeTo2D(); + (0, _ndarrayGemm.default)(this.output.tensor, this.featureMaps.tensor, this.weights.tensor, 1, 1); + this.output.reshapeFrom2D(); + } + + _ndarrayOps.default.maxseq(this.output.tensor, 0); + + if (this.featureMaps.is2DReshaped) { + this.featureMaps.reshapeFrom2D(); + } + } + + _updateGPU() { + if (!this.output) { + this.output = new _Tensor.default([], this.shape); + } + + const isWeights1D = this.weights.is1D; + + if (!this.output.glTexture && isWeights1D) { + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } else { + this.output.reshapeTo2D(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const numFeatures = isWeights1D ? this.weights.glTextureShape[1] : this.weights.glTextureShape[0]; + + if (!this.program) { + const programSource = (0, _createGLSLProgram.default)('cam', this.output.glTextureShape, numFeatures, isWeights1D); + this.program = _WebGL.webgl2.compileProgram(programSource); + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: this.featureMaps, + name: 'featureMaps' + }, { + input: this.weights, + name: 'weights' + }] + }); + + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } + } + +} + +exports.default = CAM; \ No newline at end of file diff --git a/keras-js/lib/visualizations/index.js b/keras-js/lib/visualizations/index.js new file mode 100644 index 0000000000..541e2e55a7 --- /dev/null +++ b/keras-js/lib/visualizations/index.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "CAM", { + enumerable: true, + get: function () { + return _CAM.default; + } +}); + +var _CAM = _interopRequireDefault(require("./CAM")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/convolutional/conv2d.js b/keras-js/lib/webgl/dynamic/convolutional/conv2d.js new file mode 100644 index 0000000000..764f64bb76 --- /dev/null +++ b/keras-js/lib/webgl/dynamic/convolutional/conv2d.js @@ -0,0 +1,44 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = conv2d; + +function conv2d(outputShape, inputShape, indexMapShape, useBias, hasFragments) { + const addBias = useBias ? `sum += texelFetch(bias, ivec2(out_x, 0), 0).r;` : ''; + const adjustIndicesForFragments = hasFragments ? `int fragmentIndex = int(floor(float(rowIndex) / float(${inputShape[0]}))); + rowIndex = int(mod(float(rowIndex), float(${inputShape[0]}))); + colIndex += fragmentIndex * ${inputShape[1]};` : ''; + const source = `#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D x; +uniform isampler2D indexMap; +uniform sampler2D kernel; +uniform sampler2D bias; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int i = 0; i < ${indexMapShape[1]}; ++i) { + int index = texelFetch(indexMap, ivec2(i, out_y), 0).r; + if (index != -1) { + int rowIndex = int(floor(float(index) / float(${inputShape[1]}))); + int colIndex = int(mod(float(index), float(${inputShape[1]}))); + ${adjustIndicesForFragments} + sum += texelFetch(x, ivec2(colIndex, rowIndex), 0).r * texelFetch(kernel, ivec2(out_x, i), 0).r; + } + } + + ${addBias} + outColor = vec4(sum); +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/convolutional/conv2dTranspose.js b/keras-js/lib/webgl/dynamic/convolutional/conv2dTranspose.js new file mode 100644 index 0000000000..fc9873be9a --- /dev/null +++ b/keras-js/lib/webgl/dynamic/convolutional/conv2dTranspose.js @@ -0,0 +1,43 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = conv2dTranspose; + +function conv2dTranspose(outputShape, inputShape, indexMapShape, useBias, hasFragments) { + const addBias = useBias ? `sum += texelFetch(bias, ivec2(out_x, 0), 0).r;` : ''; + const adjustIndicesForFragments = hasFragments ? `int fragmentIndex = int(floor(float(rowIndex) / float(${inputShape[0]}))); + rowIndex = int(mod(float(rowIndex), float(${inputShape[0]}))); + colIndex += fragmentIndex * ${inputShape[1]};` : ''; + const source = `#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D matMulResult; +uniform isampler2D indexMap; +uniform sampler2D bias; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int n = 0; n < ${indexMapShape[1]}; ++n) { + int index = texelFetch(indexMap, ivec2(n, out_y), 0).r; + if (index != -1) { + int rowIndex = int(floor(float(index) / float(${inputShape[1]}))); + int colIndex = int(mod(float(index), float(${inputShape[1]}))); + ${adjustIndicesForFragments} + sum += texelFetch(matMulResult, ivec2(colIndex + out_x, rowIndex), 0).r; + } + } + + ${addBias} + outColor = vec4(sum); +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/createGLSLProgram.js b/keras-js/lib/webgl/dynamic/createGLSLProgram.js new file mode 100644 index 0000000000..8273e5a7e5 --- /dev/null +++ b/keras-js/lib/webgl/dynamic/createGLSLProgram.js @@ -0,0 +1,65 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = createGLSLProgram; + +var _add = _interopRequireDefault(require("./merge/add")); + +var _average = _interopRequireDefault(require("./merge/average")); + +var _concatenate = _interopRequireDefault(require("./merge/concatenate")); + +var _maximum = _interopRequireDefault(require("./merge/maximum")); + +var _minimum = _interopRequireDefault(require("./merge/minimum")); + +var _multiply = _interopRequireDefault(require("./merge/multiply")); + +var _subtract = _interopRequireDefault(require("./merge/subtract")); + +var _conv2d = _interopRequireDefault(require("./convolutional/conv2d")); + +var _conv2dTranspose = _interopRequireDefault(require("./convolutional/conv2dTranspose")); + +var _cam = _interopRequireDefault(require("./visualizations/cam")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createGLSLProgram(program, ...args) { + switch (program) { + case 'add': + return (0, _add.default)(...args); + + case 'average': + return (0, _average.default)(...args); + + case 'concatenate': + return (0, _concatenate.default)(...args); + + case 'maximum': + return (0, _maximum.default)(...args); + + case 'minimum': + return (0, _minimum.default)(...args); + + case 'multiply': + return (0, _multiply.default)(...args); + + case 'subtract': + return (0, _subtract.default)(...args); + + case 'conv2d': + return (0, _conv2d.default)(...args); + + case 'conv2dTranspose': + return (0, _conv2dTranspose.default)(...args); + + case 'cam': + return (0, _cam.default)(...args); + + default: + throw new Error('GLSL program not found'); + } +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/merge/add.js b/keras-js/lib/webgl/dynamic/merge/add.js new file mode 100644 index 0000000000..2269359973 --- /dev/null +++ b/keras-js/lib/webgl/dynamic/merge/add.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = add; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function add(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(${(0, _range2.default)(numInputs).map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`).join(' + ')}); +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/merge/average.js b/keras-js/lib/webgl/dynamic/merge/average.js new file mode 100644 index 0000000000..0a96cf805c --- /dev/null +++ b/keras-js/lib/webgl/dynamic/merge/average.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = average; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function average(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4((${(0, _range2.default)(numInputs).map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`).join(' + ')}) / float(${numInputs})); +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/merge/concatenate.js b/keras-js/lib/webgl/dynamic/merge/concatenate.js new file mode 100644 index 0000000000..791572e061 --- /dev/null +++ b/keras-js/lib/webgl/dynamic/merge/concatenate.js @@ -0,0 +1,67 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = concatenate; + +var _take2 = _interopRequireDefault(require("lodash/take")); + +var _sum2 = _interopRequireDefault(require("lodash/sum")); + +var _range2 = _interopRequireDefault(require("lodash/range")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function concatenate(numInputs, inputShapes, outputShape, concatAxis) { + const dims = inputShapes.map(shape => shape[concatAxis]); + const offsets = (0, _range2.default)(numInputs + 1).map(i => (0, _sum2.default)((0, _take2.default)(dims, i))); + const outVar = concatAxis === 0 ? 'out_y' : 'out_x'; + let getOffset = ` + int n = 0; + int offset = 0; + if (${outVar} >= ${offsets[1]} && ${outVar} < ${offsets[2]}) { + n = 1; + offset = ${offsets[1]}; + }`; + + if (numInputs > 2) { + getOffset += `${(0, _range2.default)(2, numInputs).map(i => ` else if (${outVar} >= ${offsets[i]} && ${outVar} < ${offsets[i + 1]}) { + n = ${i}; + offset = ${offsets[i]}; + }`).join('')} +`; + } + + let outBlock = 'outColor = vec4(0.0);'; + + if (concatAxis === 0 || concatAxis === 1) { + const xCoord = i => `out_x${concatAxis === 1 ? ` - ${offsets[i]}` : ''}`; + + const yCoord = i => `out_y${concatAxis === 0 ? ` - ${offsets[i]}` : ''}`; + + outBlock = ` + if (n == 0) { + outColor = vec4(texelFetch(inputs[0], ivec2(out_x, out_y), 0).r); + }${(0, _range2.default)(1, numInputs).map(i => ` else if (n == ${i}) { + outColor = vec4(texelFetch(inputs[${i}], ivec2(${xCoord(i)}, ${yCoord(i)}), 0).r); + }`).join('')} +`; + } + + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); +${getOffset} +${outBlock} +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/merge/maximum.js b/keras-js/lib/webgl/dynamic/merge/maximum.js new file mode 100644 index 0000000000..b6c70ab45c --- /dev/null +++ b/keras-js/lib/webgl/dynamic/merge/maximum.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = maximum; + +function maximum(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + float val = texelFetch(inputs[0], ivec2(out_x, out_y), 0).r; + for (int i = 1; i < ${numInputs}; i++) { + val = max(val, texelFetch(inputs[i], ivec2(out_x, out_y), 0).r); + } + + outColor = vec4(val); +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/merge/minimum.js b/keras-js/lib/webgl/dynamic/merge/minimum.js new file mode 100644 index 0000000000..b9c97e3005 --- /dev/null +++ b/keras-js/lib/webgl/dynamic/merge/minimum.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = minimum; + +function minimum(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + float val = texelFetch(inputs[0], ivec2(out_x, out_y), 0).r; + for (int i = 1; i < ${numInputs}; i++) { + val = min(val, texelFetch(inputs[i], ivec2(out_x, out_y), 0).r); + } + + outColor = vec4(val); +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/merge/multiply.js b/keras-js/lib/webgl/dynamic/merge/multiply.js new file mode 100644 index 0000000000..8a0b9e7cc5 --- /dev/null +++ b/keras-js/lib/webgl/dynamic/merge/multiply.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = multiply; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function multiply(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(${(0, _range2.default)(numInputs).map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`).join(' * ')}); +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/merge/subtract.js b/keras-js/lib/webgl/dynamic/merge/subtract.js new file mode 100644 index 0000000000..5c4b17395c --- /dev/null +++ b/keras-js/lib/webgl/dynamic/merge/subtract.js @@ -0,0 +1,24 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = subtract; + +function subtract(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[2]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(texelFetch(inputs[0], ivec2(out_x, out_y), 0).r - texelFetch(inputs[1], ivec2(out_x, out_y), 0).r); +} +`; + return source; +} \ No newline at end of file diff --git a/keras-js/lib/webgl/dynamic/visualizations/cam.js b/keras-js/lib/webgl/dynamic/visualizations/cam.js new file mode 100644 index 0000000000..123cbb08a5 --- /dev/null +++ b/keras-js/lib/webgl/dynamic/visualizations/cam.js @@ -0,0 +1,62 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = cam; + +function cam(outputShape, numFeatures, weightsIs1D) { + let source; + + if (weightsIs1D) { + source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D featureMaps; +uniform sampler2D weights; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + int featureMapsRow = out_x + ${outputShape[0]} * out_y; + + float sum = 0.; + for (int k = 0; k < ${numFeatures}; ++k) { + float f = texelFetch(featureMaps, ivec2(k, featureMapsRow), 0).r; + float w = texelFetch(weights, ivec2(k, 0), 0).r; + sum += f * w; + } + + outColor = vec4(max(sum, 0.0)); +} +`; + } else { + source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D featureMaps; +uniform sampler2D weights; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int k = 0; k < ${numFeatures}; ++k) { + float f = texelFetch(featureMaps, ivec2(k, out_y), 0).r; + float w = texelFetch(weights, ivec2(out_x, k), 0).r; + sum += f * w; + } + + outColor = vec4(max(sum, 0.0)); +} +`; + } + + return source; +} \ No newline at end of file diff --git a/keras-js/package-lock.json b/keras-js/package-lock.json new file mode 100644 index 0000000000..4a434acaf0 --- /dev/null +++ b/keras-js/package-lock.json @@ -0,0 +1,6746 @@ +{ + "name": "keras-js", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/cli": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.0.0-beta.32.tgz", + "integrity": "sha512-X901Tj60U4gBysqGd8HQfBVPFoDBSAyV8h70rLY1zshOgmKePhnXs6W2pIlx7G1tHd9AJmtzU5PQ5Cwx2y4Upg==", + "dev": true, + "requires": { + "chokidar": "1.7.0", + "commander": "2.12.2", + "convert-source-map": "1.5.1", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.4", + "output-file-sync": "2.0.0", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/code-frame": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.32.tgz", + "integrity": "sha512-EVq4T1a2GviKiQ75OfxNrGPPhJyXzg9jjORuuwhloZbFdrhT4FHa73sv9OFWBwX7rl2b6bxBVmfxrBQYWYz9tA==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + } + } + }, + "@babel/core": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.0.0-beta.32.tgz", + "integrity": "sha512-IeYWdxmLKYmHtff+fOhWll/Ynnaohpes0KZFuuo49p3KQw7VLFsK+FKyH2btYyx2qaIxrHIMUYtQRZOXCctvLQ==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.32", + "@babel/generator": "7.0.0-beta.32", + "@babel/helpers": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "babylon": "7.0.0-beta.32", + "convert-source-map": "1.5.1", + "debug": "3.1.0", + "json5": "0.5.1", + "lodash": "4.17.4", + "micromatch": "2.3.11", + "resolve": "1.5.0", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.32.tgz", + "integrity": "sha512-JQrG+5JQmaDwyj+VL01eE9dX6PSVBfvDyRbA1AXwzk0+BcQ71++M64K2HzbVyD3sti/yjh0EUJAg0Yw9Fn7ZuQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32", + "jsesc": "2.5.1", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0-beta.32.tgz", + "integrity": "sha512-k7kaUbYARwMPbaSbbC1BqIZFQ8eXUxrzvDmI9JpJGI73ITZCFbO3R8fLkJ3rTAA+VNcBpgCrSFy6hzrkoYRJLA==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.0.0-beta.32.tgz", + "integrity": "sha512-ovdauzFqvO7iU29FLkTMUvo5w8UVyHAkexao6T8/ElxDtqZc6SbbCbgBHO9nl2jqu4gYp0Lo4ggIl1PYDwZMxQ==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-call-delegate": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.0.0-beta.32.tgz", + "integrity": "sha512-lzZt0OolIzd7S7TvUPcJVkmR3GlEPNbkPaoDeVwg0cA9GhhlBoNHVa2OUtzsiSsEGTVaa0hMbNzEYVonHERLaA==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-define-map": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.0.0-beta.32.tgz", + "integrity": "sha512-8zN3+BYcUgi6kdDuMIgZCROQZoziNw89FlBLETzfWXVZLG1GYzIQsazWUvwLxb4FaL9uFLYCfIELAylt473ZIw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.0.0-beta.32.tgz", + "integrity": "sha512-hEttRImD90IVKOabU9uQda3+gOqhA956xvoTgTwTfgiJGDW53ZF5DsYEpg1TO8+P6uZcpgO46nmDEdbi3xUk+A==", + "dev": true, + "requires": { + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.32.tgz", + "integrity": "sha512-ysfIt7p72xm5fjSJsv7fMVN/j+EwIdqu8/MJjt6TqB4wM2r6rFRi0ujBTWDkLGQkRB/P5uDV8qcFCHAHnNzmsg==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.32.tgz", + "integrity": "sha512-bm7lIlizycJQY5SJ3HXWJV4XjSrOt1onzrDcOxUo9FEnKRZDEr/zfi5ar2s5tvvZvve/jGHwZKVKekRw2cjPCQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0-beta.32.tgz", + "integrity": "sha512-mJ+VwjY/0tUHvqKGhSlEpss9OqKbx8tUF7Q89lUSdQvpIoTI91A0mCpNzMrg8Ma03C+aLJ91oa5uPIwHkrAIfA==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.32.tgz", + "integrity": "sha512-9jxfqCBrwCIa0p5ZIy1sakzKKm8x8tn0C52qpPr0M0WJ/k9gpD4ilS/mTV2v0tgmw4agjYdUXQ8slq51/5oOzQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.0.0-beta.32.tgz", + "integrity": "sha512-t1o1EiWVOgB463fplP4QBgDjthQqCWVtOpzp5P5I30FyCUH4XAyNRJyS8+cYxEbGpjM80FKf7IuRmjZhBC8trg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.0.0-beta.32", + "@babel/helper-simple-access": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0-beta.32.tgz", + "integrity": "sha512-7Y6U6biSYJekqXfp3Tv7kbNcZoO5HH7utmUkcpQzBonV8bvp3VyEnJHHsNgz5iJo2OEh7Tdzwapt88Z0j7+0dQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-regex": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0-beta.32.tgz", + "integrity": "sha512-A18MJbDz9azbk4XJVti7VXlcMjxCccpd7hHLzAlLPU8kYWAwUMHgcsnCSp2RsS7rTQky6oCGGjhrphk/Ajn2Lw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.0.0-beta.32.tgz", + "integrity": "sha512-9LC7+/c2ELr6TJD14frREbQFe39oTUHCilmXOA2sgCUALN1JDoWHbFpct0HvCWxeBHkQUzxBFiy5bwah7i2jyQ==", + "dev": true, + "requires": { + "@babel/helper-wrap-function": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-replace-supers": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.0.0-beta.32.tgz", + "integrity": "sha512-zyCvhY2WtD5zAIJs599C+ivbbtpBs6pGeVN0SEf3K1X5VvqjfUvOkc095pGEgdDJnaCNq3zWnOhOlDXI2x59Iw==", + "dev": true, + "requires": { + "@babel/helper-optimise-call-expression": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-simple-access": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.0.0-beta.32.tgz", + "integrity": "sha512-wQsW8eA2biFLwCxkRvsJNGRguUJZknkGzAZQO8wwB1uS8mgS9si0F6Bz1VPuB6O5cSF2CPsnT4jWvsat2l2DcQ==", + "dev": true, + "requires": { + "@babel/template": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/helper-wrap-function": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.0.0-beta.32.tgz", + "integrity": "sha512-iyGV+eUxmA20yNEbMm67/0EEaIRGv7g6R06Q4P4PTBye6v6RB6DEOWLw7FiUcl2o+C8VmksDcRtTfeqEe5I1kQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helpers": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.0.0-beta.32.tgz", + "integrity": "sha512-10qgCPVX3fg8yZ4+BN5iaS4/1owxzm4REpCOXivIWM+Cq1jltekmbkxDdOhHVPMU3SMGBnCsybISzP5be6yHPQ==", + "dev": true, + "requires": { + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/plugin-check-constants": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-check-constants/-/plugin-check-constants-7.0.0-beta.32.tgz", + "integrity": "sha512-Ed70DlO8vGoNZcRdQhybK2ENnwVI+nne18vV3wqKYN2ikMUv/ueUOKdZdJ0V0sGhpATeS064UX5HwFD3zu72Jw==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.0.0-beta.32.tgz", + "integrity": "sha512-slu0JQDCcETHJ9teGqc75Lt04XRomWMDeAA9JXJGuKBXlTwq/+rlfK1LQze5M8+/onW9PAr/cqpCZ9Q8bn4j9g==", + "dev": true, + "requires": { + "@babel/helper-remap-async-to-generator": "7.0.0-beta.32", + "@babel/plugin-syntax-async-generators": "7.0.0-beta.32" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.0.0-beta.32.tgz", + "integrity": "sha512-waZLn49DpreTFG1aeZhZQZlZjwltuk5cnZvz1Z2VjHEEQhzznRQqeOEwJLot9HjxvFnS7eQRCzu3QAzQv8FMRQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/plugin-syntax-class-properties": "7.0.0-beta.32" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0-beta.32.tgz", + "integrity": "sha512-l8kaLgrzCdgS3juF57d6xywBYAVxoKJLjffTYym7frGmu7Cc4U1mpPg4kNn2aQS+BleA/7JgBNpvuL4An2L3GQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "7.0.0-beta.32" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0-beta.32.tgz", + "integrity": "sha512-Rkf9P+VInhRJhLA8SPP6XGu5/8DpBXE5x6tiEh5Cn+1R0WvU3B1cNcMcww8XMzT7Jl3B0kDVkU28/+75N7WAqA==", + "dev": true, + "requires": { + "@babel/plugin-syntax-optional-catch-binding": "7.0.0-beta.32" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0-beta.32.tgz", + "integrity": "sha512-8TEs0YpAgbOMclfua/46XZZDtU5AIIx0FgsZrO/ijP9p4XCP93JbPfU8Y6lpSRr8HPm4hPRGFZgwyAuAo0SQ4A==", + "dev": true, + "requires": { + "@babel/helper-regex": "7.0.0-beta.32", + "regexpu-core": "4.1.3" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0-beta.32.tgz", + "integrity": "sha512-FfWnqZ9LsPqTJiYXSOlfoVTBf/WdwZh/tnhXoGAK0Y77ExfcAaJqIqt0QalHHFxLy5uIewgkRilkXTk+qZV2OA==", + "dev": true + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0-beta.32.tgz", + "integrity": "sha512-9PF0kjGQDnpszttGbDuypjqB6rCbu3WTSpBXkCmmgwHmDMXiCXxwAUpZFjrtCgjxVA0q4rVwl2tCfCjVkgBk8w==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0-beta.32.tgz", + "integrity": "sha512-xqXOiFUnziFWIGTqI+tqEU4RL6qTJqpwJh89LoOi+QksH3/YrKvIA7pHUn3Jd0z2QUeZa2XaqTKRjzLX+gmZ+g==", + "dev": true + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0-beta.32.tgz", + "integrity": "sha512-wu8wvUVE3FhnyGY1d1R1sWkgnPwV9pqsHRq/XLZcNIcFwDdUvWWzyCGqkajzvvgFV+9w/QMd2WBcOUsUGXkEFA==", + "dev": true + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0-beta.32.tgz", + "integrity": "sha512-Id82/I8+ZRgQuE6oRRGkgKg1P11eSZ6sNLk20OQQUk3i5u4SGeaagpDiRJ5evgE2gM7ECYfR02yyFmiclOSwVg==", + "dev": true + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.0.0-beta.32.tgz", + "integrity": "sha512-OsQskJJA3GuKECVEzUMQ40b4/ZWZwCQLw3qPN8Dvzl3jJ577JdPRmh38EaDrYhCRv34R9RfdWEWLfaUoYbocLQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.0.0-beta.32", + "@babel/helper-remap-async-to-generator": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0-beta.32.tgz", + "integrity": "sha512-Fg6X0h6GF3v9JnO7907Niv5S9maDnPOqtRGoFQvk5CccCOuEya3xdJY/KwvI7eFpygo79CRUzA+dGT6BIJnqHw==", + "dev": true + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0-beta.32.tgz", + "integrity": "sha512-wpgRdXmUk27+ztlhtrQwNsx1CqJgyh30jQZ8MDBpG2vH/+P1rS7ZoKMsNVSu7RvSCuZDusS+Sg9Y7xMs7SnnsQ==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.0.0-beta.32.tgz", + "integrity": "sha512-cgI+ktFC6FKbWI+AGA4/ia2sE/b1AOpFcYk8PpnNAOLp4IS+OtpGqntDVBXvJvnzo/V6+afrh6sl9WrIz3hYpA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "7.0.0-beta.32", + "@babel/helper-define-map": "7.0.0-beta.32", + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/helper-optimise-call-expression": "7.0.0-beta.32", + "@babel/helper-replace-supers": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0-beta.32.tgz", + "integrity": "sha512-xt/hR2r+LEfTvISzCmozUT0DVAh0PfhA+Z++qAnkKg9l/evG4eTkzeVe1mdJdLjCpYlqj2qloxos3L79eYh3rQ==", + "dev": true + }, + "@babel/plugin-transform-destructuring": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.0.0-beta.32.tgz", + "integrity": "sha512-fT0UIbRL4wfUTqHSMMEBVougn48fWm2vjOkB6rBqMt+hdSwarcTs1vcZkol5ZDwLB731ZVJ761Lo2fTWBqDcUQ==", + "dev": true + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0-beta.32.tgz", + "integrity": "sha512-Obktgcju396fmESjnailU4qZnoYbNzQWx7JiRts6/dXFbM6mYfPclUpxy/HuBbn/0oR6qRAMuPrAJPD0yi1+Wg==", + "dev": true + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.0.0-beta.32.tgz", + "integrity": "sha512-Xvyx5BdBL2Y477bDPjmyb4eQoMxoqwW2g2hlwssVfHnvLP0JqM3tMB0RNfAE2XjkIMoBNVUSwVVCbH8XFWEWxg==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0-beta.32.tgz", + "integrity": "sha512-ZtqM+YVsF+AcVo+lFhkjObBrifD/tRFbjHVGCw79Y9imNqn8KIlC2NAN7dcz/G5A5Qn87KYwug5kyJ79PHoeDA==", + "dev": true + }, + "@babel/plugin-transform-function-name": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.0.0-beta.32.tgz", + "integrity": "sha512-+6ZET0e1/kvmgilGpjwGdGNt/7Hmre9vxvhVIw1ztbM+se4iEKP79lceLNA+red22jnlNzRHVo5KzbU7vCNLwA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0-beta.32.tgz", + "integrity": "sha512-uBXC+JcYALYHkXRZZD49mwD0n1ufWu8lbuHEIjpPvEncp63zklVgV5q1XkhXR7Dm1PWDCuEy8Aj6I0La/PBSmQ==", + "dev": true + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.0.0-beta.32.tgz", + "integrity": "sha512-JmwSwyznAcOsIvgD6uVGA0gB4pAVfn5KveUAKeF/3gWbCmaVtsb8D3N8VEnOmzG9C68/qdPVYs07fFeyyrShCQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.0.0-beta.32.tgz", + "integrity": "sha512-kq2Up4V7l3qdJ3RKiHDyf4hr11uBeBBjf+bi53BcJRtU3/dATSXnJ3UPTWyRs2PVj0geGX61ereyHgP+eUOusA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "7.0.0-beta.32", + "@babel/helper-simple-access": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0-beta.32.tgz", + "integrity": "sha512-JMGVoc03u1BHebJVuDSZ37ZmNAsxsRsVq3rJb7piLOM4k0TTdD0wyAPjNk8+/90kPaFFeP6qhpkUqgAed1Y2Jg==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.0.0-beta.32.tgz", + "integrity": "sha512-z9KLuONpgUz1iBbE2iWCfT1y0GF+aqideaqXlemLg4oqudd52EBfopMMicKh1/2KuIQEG+CQljoURTikanUYww==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0-beta.32.tgz", + "integrity": "sha512-TC0RqzMvCK8A5/kRzrQItS4SiiNOev9Bui861PDNAQBNIJvv2MyPUpOcV5VyCsiGIw4XMDMfcU2DngfzIWq4QQ==", + "dev": true + }, + "@babel/plugin-transform-object-super": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.0.0-beta.32.tgz", + "integrity": "sha512-5rcRZ9fFt8EXSz4r/BdlQi/LlUlCl07RBb0rm3VplAfN/+g1G1rcYCyivXHuhibVkvrdSAMbYZrQv955+WuRtg==", + "dev": true, + "requires": { + "@babel/helper-replace-supers": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.0.0-beta.32.tgz", + "integrity": "sha512-LSp9l0n2Xayn8gidVGunCRtyxEAagSahqZgncw3ERkOrwTNlpfE6eaZTqxp/r2kx6kHYt1md/OIaIAxGhCw0+A==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "7.0.0-beta.32", + "@babel/helper-get-function-arity": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0-beta.32.tgz", + "integrity": "sha512-AVZFTyFTOk1E5MC3NnSwVh0rWgVLOK2D+DqLVknaAVEU29ZKPKLVgoGJOwEPTQS99GWlRh3yAZ8jGMQT6ZiDpA==", + "dev": true, + "requires": { + "regenerator-transform": "0.11.1" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0-beta.32.tgz", + "integrity": "sha512-oLzdWzXqHrqCfGpFXoetpnaNCAzrqTnEysKYoAgv6f+R3su4y8KXXi80eg0/rTNwZ+i3N3hDC+Ipq5+eSVl4Iw==", + "dev": true + }, + "@babel/plugin-transform-spread": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0-beta.32.tgz", + "integrity": "sha512-e2d+Ee/mn5Kcj/okt+WqyLswuXs3QIgEdXwtN5M9d609y1mCWZN3Bdz7F6HiFoFF5R24dG8nqymRUzbR+Pn2UA==", + "dev": true + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0-beta.32.tgz", + "integrity": "sha512-HvgKJ1j6ziYbphvn7QCvTHk6K/TeqNo3dFdHfv7KgXQYxz/OQV8hxCE4SK6nqesrQftOBWeZlNotexcA8qVRSw==", + "dev": true, + "requires": { + "@babel/helper-regex": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0-beta.32.tgz", + "integrity": "sha512-mUohId4FHet/HxQsJVl9MdakfgxoA5GfE32xSTyZePOZz1kzNVRndx82M7wRSjDqr5Ry9BebTtNagR5Rhd2+EQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0-beta.32.tgz", + "integrity": "sha512-AILpoMhhFg8el2YZSUIw3sZiy+4wvzDOUBPvbvDlJEjUk2wyZpfsZDv5FzY2LiWeRQxg1Ce06slPzaEMIOxEyw==", + "dev": true + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0-beta.32.tgz", + "integrity": "sha512-paFzs6VyyCxqfuCVVPKe9ASZ50cKaSWwnygmBTZzKt3sdI1YX8KZ4fSgeiqHsR1sIZzJC6oLAiTajMZO8vJyIQ==", + "dev": true, + "requires": { + "@babel/helper-regex": "7.0.0-beta.32", + "regexpu-core": "4.1.3" + } + }, + "@babel/preset-env": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.0.0-beta.32.tgz", + "integrity": "sha512-vzWR4oSse4HhDeB+7KHuY0X0WTrl1w+XBGYvceJby/Q3DuqcRxY+gyw+s82gnjxsh/k+bGwcdkWpnGRQPtDVcw==", + "dev": true, + "requires": { + "@babel/plugin-check-constants": "7.0.0-beta.32", + "@babel/plugin-proposal-async-generator-functions": "7.0.0-beta.32", + "@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.32", + "@babel/plugin-proposal-optional-catch-binding": "7.0.0-beta.32", + "@babel/plugin-proposal-unicode-property-regex": "7.0.0-beta.32", + "@babel/plugin-syntax-async-generators": "7.0.0-beta.32", + "@babel/plugin-syntax-object-rest-spread": "7.0.0-beta.32", + "@babel/plugin-syntax-optional-catch-binding": "7.0.0-beta.32", + "@babel/plugin-transform-arrow-functions": "7.0.0-beta.32", + "@babel/plugin-transform-async-to-generator": "7.0.0-beta.32", + "@babel/plugin-transform-block-scoped-functions": "7.0.0-beta.32", + "@babel/plugin-transform-block-scoping": "7.0.0-beta.32", + "@babel/plugin-transform-classes": "7.0.0-beta.32", + "@babel/plugin-transform-computed-properties": "7.0.0-beta.32", + "@babel/plugin-transform-destructuring": "7.0.0-beta.32", + "@babel/plugin-transform-duplicate-keys": "7.0.0-beta.32", + "@babel/plugin-transform-exponentiation-operator": "7.0.0-beta.32", + "@babel/plugin-transform-for-of": "7.0.0-beta.32", + "@babel/plugin-transform-function-name": "7.0.0-beta.32", + "@babel/plugin-transform-literals": "7.0.0-beta.32", + "@babel/plugin-transform-modules-amd": "7.0.0-beta.32", + "@babel/plugin-transform-modules-commonjs": "7.0.0-beta.32", + "@babel/plugin-transform-modules-systemjs": "7.0.0-beta.32", + "@babel/plugin-transform-modules-umd": "7.0.0-beta.32", + "@babel/plugin-transform-new-target": "7.0.0-beta.32", + "@babel/plugin-transform-object-super": "7.0.0-beta.32", + "@babel/plugin-transform-parameters": "7.0.0-beta.32", + "@babel/plugin-transform-regenerator": "7.0.0-beta.32", + "@babel/plugin-transform-shorthand-properties": "7.0.0-beta.32", + "@babel/plugin-transform-spread": "7.0.0-beta.32", + "@babel/plugin-transform-sticky-regex": "7.0.0-beta.32", + "@babel/plugin-transform-template-literals": "7.0.0-beta.32", + "@babel/plugin-transform-typeof-symbol": "7.0.0-beta.32", + "@babel/plugin-transform-unicode-regex": "7.0.0-beta.32", + "browserslist": "2.9.1", + "invariant": "2.2.2", + "semver": "5.4.1" + } + }, + "@babel/template": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.32.tgz", + "integrity": "sha512-DB9sLgX2mfE29vjAkxHlzLyWr31EO9HaYoAM/UsPSsL70Eudl0i25URwIfQT6S6ckeVFnFP1t6PhERVeV4EAHA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "babylon": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.32.tgz", + "integrity": "sha512-dGe2CLduCIZ/iDkbmnqspQguRy5ARvI+zC8TiwFnsJ2YYO2TWK7x2aEwrbkSmi0iPlBP+Syiag7Idc1qNQq74g==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.32", + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "babylon": "7.0.0-beta.32", + "debug": "3.1.0", + "globals": "10.4.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "@babel/types": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.32.tgz", + "integrity": "sha512-w8+wzVcYCMb9OfaBfay2Vg5hyj7UfBX6qQtA+kB0qsW1h1NH/7xHMwvTZNqkuFBwjz5wxGS2QmaIcC3HH+UoxA==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + }, + "dependencies": { + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + } + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/inquire": "1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/events": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz", + "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw==" + }, + "@types/long": { + "version": "3.0.32", + "resolved": "https://registry.npmjs.org/@types/long/-/long-3.0.32.tgz", + "integrity": "sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA==" + }, + "@types/node": { + "version": "8.0.54", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.54.tgz", + "integrity": "sha512-qetMdTv3Ytz9u9ESLdcYs45LPI0mczYZIbC184n7kY0jczOqPNQsabBfVCh+na3B2shAfvC459JqHV771A8Rxg==", + "requires": { + "@types/events": "1.1.0" + } + }, + "absolute": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/absolute/-/absolute-0.0.1.tgz", + "integrity": "sha1-wigi+H4ck59XmIdQTZwQnEFzgp0=" + }, + "acorn": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==" + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz", + "integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + }, + "dependencies": { + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + } + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==" + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "requires": { + "color-convert": "1.9.1" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "asn1.js": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", + "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "dev": true + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "requires": { + "lodash": "4.17.4" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "requires": { + "follow-redirects": "1.2.6", + "is-buffer": "1.1.6" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.0.3.tgz", + "integrity": "sha512-7D4iUpylEiKJPGbeSAlNddGcmA41PadgZ6UAb6JVyh003h3d0EbZusYFBR/+nBgqtaVJM2J2zUVa3N0hrpMH6g==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.31", + "@babel/traverse": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.31.tgz", + "integrity": "sha512-yd7CkUughvHQoEahQqcMdrZw6o/6PwUxiRkfZuVDVHCDe77mysD/suoNyk5mK6phTnRW1kyIbPHyCJgxw++LXg==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.31.tgz", + "integrity": "sha512-c+DAyp8LMm2nzSs2uXEuxp4LYGSUYEyHtU3fU57avFChjsnTmmpWmXj2dv0yUxHTEydgVAv5fIzA+4KJwoqWDA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.31", + "@babel/template": "7.0.0-beta.31", + "@babel/traverse": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.31.tgz", + "integrity": "sha512-m7rVVX/dMLbbB9NCzKYRrrFb0qZxgpmQ4Wv6y7zEsB6skoJHRuXVeb/hAFze79vXBbuD63ci7AVHXzAdZSk9KQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.31" + } + }, + "@babel/template": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.31.tgz", + "integrity": "sha512-97IRmLvoDhIDSQkqklVt3UCxJsv0LUEVb/0DzXWtc8Lgiyxj567qZkmTG9aR21CmcJVVIvq2Y/moZj4oEpl5AA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31", + "lodash": "4.17.4" + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.31.tgz", + "integrity": "sha512-3N+VJW+KlezEjFBG7WSYeMyC5kIqVLPb/PGSzCDPFcJrnArluD1GIl7Y3xC7cjKiTq2/JohaLWHVPjJWHlo9Gg==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.31", + "@babel/helper-function-name": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31", + "debug": "3.1.0", + "globals": "10.4.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "@babel/types": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.31.tgz", + "integrity": "sha512-exAHB+NeFGxkfQ5dSUD03xl3zYGneeSk2Mw2ldTt/nTvYxuDiuSp3DlxgUBgzbdTFG4fbwPk0WtKWOoTXCmNGg==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + } + }, + "babylon": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz", + "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ==", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + } + } + }, + "babel-helper-module-imports": { + "version": "7.0.0-beta.3", + "resolved": "https://registry.npmjs.org/babel-helper-module-imports/-/babel-helper-module-imports-7.0.0-beta.3.tgz", + "integrity": "sha512-bdPrIXbUTYfREhRhjbN8SstwQaj0S4+rW4PKi1f2Wc5fizSh0hGYkfXUdiSSOgyTydm956tAyz4FrG61bqdQyw==", + "dev": true, + "requires": { + "babel-types": "7.0.0-beta.3", + "lodash": "4.17.4" + } + }, + "babel-loader": { + "version": "8.0.0-beta.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.0-beta.0.tgz", + "integrity": "sha512-qVXXyIqTrLBH3Ki2VCJog1fUd6qzKUk9lHS34WJPW93Bh0BUvXTFSD5ZkG3a5+Uxxje+RgCk8Y7RyB6zyK9rWw==", + "dev": true, + "requires": { + "find-cache-dir": "1.0.0", + "loader-utils": "1.1.0", + "mkdirp": "0.5.1" + } + }, + "babel-plugin-inline-import": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/babel-plugin-inline-import/-/babel-plugin-inline-import-2.0.6.tgz", + "integrity": "sha1-ijwXlWG1A79K8xnzytQ15reyhjw=", + "dev": true, + "requires": { + "require-resolve": "0.0.2" + } + }, + "babel-plugin-lodash": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-lodash/-/babel-plugin-lodash-3.3.2.tgz", + "integrity": "sha512-lNsptTRfc0FTdW56O087EiKEADVEjJo2frDQ97olMjCKbRZfZPu7MvdyxnZLOoDpuTCtavN8/4Zk65x4gT+C3Q==", + "dev": true, + "requires": { + "babel-helper-module-imports": "7.0.0-beta.3", + "babel-types": "6.26.0", + "glob": "7.1.2", + "lodash": "4.17.4", + "require-package-name": "2.0.1" + }, + "dependencies": { + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.1", + "regenerator-runtime": "0.11.0" + } + }, + "babel-types": { + "version": "7.0.0-beta.3", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-7.0.0-beta.3.tgz", + "integrity": "sha512-36k8J+byAe181OmCMawGhw+DtKO7AwexPVtsPXoMfAkjtZgoCX3bEuHWfdE5sYxRM8dojvtG/+O08M0Z/YDC6w==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + }, + "dependencies": { + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + } + } + }, + "babylon": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.32.tgz", + "integrity": "sha512-PvAmyP2IJEBVAuE5yVzrTSWCCN9VMa1eGns8w3w6FYD/ivHSUmS7n+F40Fmjn+0nCQSUFR96wP0CqQ4jxTnF4Q==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bit-twiddle": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz", + "integrity": "sha1-DGwfq+KyPRcXPZpht7cJPrnhdp4=" + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "requires": { + "readable-stream": "2.3.3" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.5" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "browserslist": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.9.1.tgz", + "integrity": "sha512-3n3nPdbUqn3nWmsy4PeSQthz2ja1ndpoXta+dwFFNhveGjMg6FXpWYe12vsTpNoXJbzx3j7GZXdtoVIdvh3JbA==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000778", + "electron-to-chromium": "1.3.28" + } + }, + "buffer": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", + "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "requires": { + "base64-js": "0.0.8", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "caniuse-lite": { + "version": "1.0.30000778", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000778.tgz", + "integrity": "sha1-8efLixOx9nREAikddfC81MMWA2k=", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "requires": { + "get-proxy": "2.1.0", + "isurl": "1.0.0", + "tunnel-agent": "0.6.0", + "url-to-options": "1.0.1" + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "dev": true, + "requires": { + "assertion-error": "1.0.2", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.5" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-spinners": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.1.0.tgz", + "integrity": "sha1-8YR7FohE2RemceudFH499JfJDQY=" + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=" + }, + "co": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", + "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=" + }, + "co-from-stream": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/co-from-stream/-/co-from-stream-0.0.0.tgz", + "integrity": "sha1-GlzYztdyY5RglPo58kmaYyl7yvk=", + "requires": { + "co-read": "0.0.1" + } + }, + "co-fs-extra": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/co-fs-extra/-/co-fs-extra-1.2.1.tgz", + "integrity": "sha1-O2rXfPJhRTD2d7HPYmZPW6dWtyI=", + "requires": { + "co-from-stream": "0.0.0", + "fs-extra": "0.26.7", + "thunkify-wrap": "1.0.4" + } + }, + "co-read": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/co-read/-/co-read-0.0.1.tgz", + "integrity": "sha1-+Bs+uKhmdf7FHj2IOn9WToc8k4k=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==" + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "requires": { + "ini": "1.3.5", + "proto-list": "1.2.4" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "consolidate": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", + "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", + "requires": { + "bluebird": "3.5.1" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.9" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.5", + "randomfill": "1.0.3" + } + }, + "cwise": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/cwise/-/cwise-1.0.10.tgz", + "integrity": "sha1-JO7mBy69/WuMb12tsXCQtkmxK+8=", + "requires": { + "cwise-compiler": "1.1.3", + "cwise-parser": "1.0.3", + "static-module": "1.5.0", + "uglify-js": "2.8.29" + } + }, + "cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "requires": { + "uniq": "1.0.1" + } + }, + "cwise-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cwise-parser/-/cwise-parser-1.0.3.tgz", + "integrity": "sha1-jkk8F9VPl8sDCp6YVLyGyd+zVP4=", + "requires": { + "esprima": "1.2.5", + "uniq": "1.0.1" + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "requires": { + "decompress-tar": "4.1.1", + "decompress-tarbz2": "4.1.1", + "decompress-targz": "4.1.1", + "decompress-unzip": "4.0.1", + "graceful-fs": "4.1.11", + "make-dir": "1.1.0", + "pify": "2.3.0", + "strip-dirs": "2.1.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "5.2.0", + "is-stream": "1.1.0", + "tar-stream": "1.5.5" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "4.1.1", + "file-type": "6.2.0", + "is-stream": "1.1.0", + "seek-bzip": "1.0.5", + "unbzip2-stream": "1.2.5" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "4.1.1", + "file-type": "5.2.0", + "is-stream": "1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "3.9.0", + "get-stream": "2.3.1", + "pify": "2.3.0", + "yauzl": "2.9.1" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } + } + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.5" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.5" + } + }, + "doctrine": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz", + "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==", + "dev": true, + "requires": { + "esutils": "2.0.2" + }, + "dependencies": { + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + } + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", + "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", + "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "download": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/download/-/download-5.0.3.tgz", + "integrity": "sha1-Y1N/l3+ZJmow64oqL70fILgAD3o=", + "requires": { + "caw": "2.0.1", + "decompress": "4.2.0", + "filenamify": "2.0.0", + "get-stream": "3.0.0", + "got": "6.7.1", + "mkdirp": "0.5.1", + "pify": "2.3.0" + } + }, + "download-git-repo": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/download-git-repo/-/download-git-repo-1.0.1.tgz", + "integrity": "sha1-1isHq+gpQx6f7JDVVDWXZkIo8wU=", + "requires": { + "download": "5.0.3", + "git-clone": "0.1.0", + "rimraf": "2.6.2" + } + }, + "dup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dup/-/dup-1.0.0.tgz", + "integrity": "sha1-UfxaxoX4GWRp3wuQXpNLIK9bQCk=" + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ecstatic": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-2.2.1.tgz", + "integrity": "sha512-ztE4WqheoWLh3wv+HQwy7dACnvNY620coWpa+XqY6R2cVWgaAT2lUISU1Uf7JpdLLJCURktJOaA9av2AOzsyYQ==", + "dev": true, + "requires": { + "he": "1.1.1", + "mime": "1.6.0", + "minimist": "1.2.0", + "url-join": "2.0.2" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "electron-to-chromium": { + "version": "1.3.28", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.28.tgz", + "integrity": "sha1-jdTmRYCGZE6fnwoc8y4qH53/2e4=", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "enable": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/enable/-/enable-1.3.2.tgz", + "integrity": "sha1-nrpoN9FtCYK1n4fYib91REPVKTE=" + }, + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "requires": { + "once": "1.4.0" + } + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "errno": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "dev": true, + "requires": { + "prr": "0.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es5-ext": { + "version": "0.10.37", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", + "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", + "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", + "requires": { + "esprima": "1.1.1", + "estraverse": "1.5.1", + "esutils": "1.0.0", + "source-map": "0.1.43" + }, + "dependencies": { + "esprima": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", + "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.9", + "doctrine": "2.0.2", + "escope": "3.6.0", + "espree": "3.5.2", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "0.12.0", + "is-my-json-valid": "2.16.1", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "shelljs": "0.7.8", + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.4", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "eslint-plugin-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-2.0.3.tgz", + "integrity": "sha1-fImIOrDIX6XSi2ZqFKTpBqqQuJc=", + "dev": true, + "requires": { + "htmlparser2": "3.9.2" + } + }, + "eslint-plugin-vue-libs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue-libs/-/eslint-plugin-vue-libs-1.2.1.tgz", + "integrity": "sha512-GSmpfPqSX4d1Etnuh/w98qLw1voc1HYAF9nqROUTwKVz/d3mJEnuR9rJn8XDzBG1ddErBgO11kLI3TUVMNdJ+A==", + "dev": true, + "requires": { + "eslint-plugin-html": "2.0.3" + } + }, + "espree": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "dev": true, + "requires": { + "acorn": "5.2.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=" + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "estraverse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" + }, + "esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "falafel": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", + "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "requires": { + "acorn": "5.2.1", + "foreach": "2.0.5", + "isarray": "0.0.1", + "object-keys": "1.0.11" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "requires": { + "pend": "1.2.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=" + }, + "filenamify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.0.0.tgz", + "integrity": "sha1-vRYiYsC26Uv7zc8Zo7uzdk94VpU=", + "requires": { + "filename-reserved-regex": "2.0.0", + "strip-outer": "1.0.0", + "trim-repeated": "1.0.0" + } + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "make-dir": "1.1.0", + "pkg-dir": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "follow-redirects": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.6.tgz", + "integrity": "sha512-FrMqZ/FONtHnbqO651UPpfRUVukIEwJhXMfdr/JWAmrDbeYBu773b1J6gdWDyRIj4hvvzQEHoEOTrdR8o6KLYA==", + "requires": { + "debug": "3.1.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "requires": { + "npm-conf": "1.1.3" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "git-clone": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/git-clone/-/git-clone-0.1.0.tgz", + "integrity": "sha1-DXYWN3gJOu9/HDAjjyqe8/B6Lrk=" + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-10.4.0.tgz", + "integrity": "sha512-uNUtxIZpGyuaq+5BqGGQHsL4wUlJAXRqOm6g3Y48/CWNGTLONgBibI0lh6lGxjR2HljFYUfszb+mk4WkgMntsA==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "gray-matter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz", + "integrity": "sha1-MELZrewqHe1qdwep7SOA+KF6Qw4=", + "requires": { + "ansi-red": "0.1.1", + "coffee-script": "1.12.7", + "extend-shallow": "2.0.1", + "js-yaml": "3.10.0", + "toml": "2.3.3" + } + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.5.1", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "has-generators": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-generators/-/has-generators-1.0.1.tgz", + "integrity": "sha1-pqLlVIYBGUBILhPiyTeRxEms9Ek=" + }, + "has-symbol-support-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz", + "integrity": "sha512-JkaetveU7hFbqnAC1EV1sF4rlojU2D4Usc5CmS69l6NfmPDnpnFUegzFg33eDkkpNCxZ0mQp65HwUDrNFS/8MA==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "1.4.1" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.4.1", + "domutils": "1.6.2", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } + }, + "http-server": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.10.0.tgz", + "integrity": "sha1-sqRGsWqduH7TxiK6m+sbCFsSNKc=", + "dev": true, + "requires": { + "colors": "1.0.3", + "corser": "2.0.1", + "ecstatic": "2.2.1", + "http-proxy": "1.16.2", + "opener": "1.4.3", + "optimist": "0.6.1", + "portfinder": "1.0.13", + "union": "0.4.6" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, + "is": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", + "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.4", + "readable-stream": "2.3.3" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, + "metalsmith": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/metalsmith/-/metalsmith-2.3.0.tgz", + "integrity": "sha1-gzr7taKmOF4tmuPZNeOeM+rqUjE=", + "requires": { + "absolute": "0.0.1", + "chalk": "1.1.3", + "clone": "1.0.3", + "co-fs-extra": "1.2.1", + "commander": "2.12.2", + "gray-matter": "2.1.1", + "has-generators": "1.0.1", + "is": "3.2.1", + "is-utf8": "0.2.1", + "recursive-readdir": "2.2.1", + "rimraf": "2.6.2", + "stat-mode": "0.2.2", + "thunkify": "2.1.2", + "unyield": "0.0.1", + "ware": "1.3.0", + "win-fork": "1.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ndarray": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", + "requires": { + "iota-array": "1.0.0", + "is-buffer": "1.1.6" + } + }, + "ndarray-blas-level1": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ndarray-blas-level1/-/ndarray-blas-level1-1.1.3.tgz", + "integrity": "sha1-7BXPrO2BmH1lGgizcf+3u929eYI=" + }, + "ndarray-blas-level2": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ndarray-blas-level2/-/ndarray-blas-level2-1.1.0.tgz", + "integrity": "sha1-s6YUC5oj/qOg+KE6klwpzP6qzkw=", + "requires": { + "ndarray-blas-level1": "1.1.3" + } + }, + "ndarray-concat-rows": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-concat-rows/-/ndarray-concat-rows-1.0.1.tgz", + "integrity": "sha1-1/h3kmXvw6mniLsU4pf6Hh8CF8M=", + "requires": { + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0", + "util-extend": "1.0.3" + } + }, + "ndarray-fft": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-fft/-/ndarray-fft-1.0.3.tgz", + "integrity": "sha1-3Fu6GOOrgsmXrbrrt455+CyToio=", + "requires": { + "bit-twiddle": "1.0.2", + "cwise": "1.0.10", + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "ndarray-gemm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-gemm/-/ndarray-gemm-1.0.0.tgz", + "integrity": "sha1-POWbMc9eIkPIZfBpQ/e0cUz7se4=" + }, + "ndarray-ops": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ndarray-ops/-/ndarray-ops-1.2.2.tgz", + "integrity": "sha1-WeiNLDKn7ryxvGkPrhQVeVV6YU4=", + "requires": { + "cwise-compiler": "1.1.3" + } + }, + "ndarray-resample": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-resample/-/ndarray-resample-1.0.1.tgz", + "integrity": "sha1-Qrsz9qS3OMV/9zxgzCINTPx1gh0=", + "requires": { + "cwise": "1.0.10", + "ndarray-fft": "1.0.3", + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0" + } + }, + "ndarray-scratch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ndarray-scratch/-/ndarray-scratch-1.2.0.tgz", + "integrity": "sha1-YwRjbWLrqT20cnrBPGkzQdulDgE=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "ndarray-squeeze": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ndarray-squeeze/-/ndarray-squeeze-1.0.2.tgz", + "integrity": "sha1-diXGnGcMv0YHkuigEd6NBHKU02w=", + "requires": { + "ndarray": "1.0.18" + } + }, + "ndarray-tile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-tile/-/ndarray-tile-1.0.3.tgz", + "integrity": "sha1-eibjlGz43xieqTXHVnmB7Ma4IPo=", + "requires": { + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0" + } + }, + "ndarray-unpack": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-unpack/-/ndarray-unpack-1.0.0.tgz", + "integrity": "sha1-S1PHZzAKXjkJuLUiWrVcbohtkdw=", + "requires": { + "cwise": "1.0.10", + "dup": "1.0.0" + } + }, + "ndarray-unsqueeze": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-unsqueeze/-/ndarray-unsqueeze-1.0.3.tgz", + "integrity": "sha1-3DqNoZx7meukGYgDbeX88pPIqwg=", + "requires": { + "ndarray": "1.0.18" + } + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.1.7", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.3", + "stream-browserify": "2.0.1", + "stream-http": "2.7.2", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.4", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "requires": { + "config-chain": "1.1.11", + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-0.4.0.tgz", + "integrity": "sha1-9RV8EWwUVbJDsG7pdwM5LFrYn+w=" + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "1.1.0" + } + }, + "opener": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.2" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "ora": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-1.3.0.tgz", + "integrity": "sha1-gAeN0rkqk0r2ajrXKluRBpTt5Ro=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "2.1.0", + "cli-spinners": "1.1.0", + "log-symbols": "1.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + }, + "dependencies": { + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + } + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "output-file-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.0.tgz", + "integrity": "sha1-XTSKGh6u0a0WhkigGi1tEweM6Yc=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "is-plain-obj": "1.1.0", + "mkdirp": "0.5.1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.2", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-extra": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/path-extra/-/path-extra-1.0.3.tgz", + "integrity": "sha1-fBEhiablDVlXkOetIDfkTkEMEWY=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "2.1.0" + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "portfinder": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", + "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", + "dev": true, + "requires": { + "async": "1.5.2", + "debug": "2.6.9", + "mkdirp": "0.5.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, + "protobufjs": { + "version": "6.8.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.3.tgz", + "integrity": "sha512-/iQhTYnSniRNmdRF9Kvw8odMSokwNOWVDOmMJjW64+EVE6igcdj/82Op/4MJ/WimgMRNac7gChlSVX4Gep/tHg==", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/base64": "1.1.2", + "@protobufjs/codegen": "2.0.4", + "@protobufjs/eventemitter": "1.1.0", + "@protobufjs/fetch": "1.1.0", + "@protobufjs/float": "1.0.2", + "@protobufjs/inquire": "1.1.0", + "@protobufjs/path": "1.1.2", + "@protobufjs/pool": "1.1.0", + "@protobufjs/utf8": "1.1.0", + "@types/long": "3.0.32", + "@types/node": "8.0.54", + "long": "3.2.0" + } + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.5" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "quote-stream": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-0.0.0.tgz", + "integrity": "sha1-zeKelMQJsW4Z3HCYuJtmWPlyHTs=", + "requires": { + "minimist": "0.0.8", + "through2": "0.4.2" + } + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", + "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "dev": true, + "requires": { + "randombytes": "2.0.5", + "safe-buffer": "5.1.1" + } + }, + "read-metadata": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-metadata/-/read-metadata-1.0.0.tgz", + "integrity": "sha1-bfnL5RGE6M630GaLQO5Rkebz2sY=", + "requires": { + "yaml-js": "0.0.8" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.5.0" + } + }, + "recursive-readdir": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.1.tgz", + "integrity": "sha1-kO8jHQd4xc4JPJpI105cVCLROpk=", + "requires": { + "minimatch": "3.0.3" + }, + "dependencies": { + "minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-5.1.3.tgz", + "integrity": "sha512-Yjy6t7jFQczDhYE+WVm7pg6gWYE258q4sUkk9qDErwXJIqx7jU9jGrMFHutJK/SRfcg7MEkXjGaYiVlOZyev/A==", + "dev": true, + "requires": { + "regenerate": "1.3.3" + } + }, + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "dev": true + }, + "regenerator-transform": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.11.1.tgz", + "integrity": "sha512-q8SAPMEyARQHzyXNWNrlz5oNnI6k4yo8ncEcvH1aXjUCqyVQ7TeV/AttqBLcySCReXVk/+fUydo/RaEIAOnRfA==", + "dev": true, + "requires": { + "babel-types": "7.0.0-beta.3", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regexpu-core": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.1.3.tgz", + "integrity": "sha512-mB+njEzO7oezA57IbQxxd6fVPOeWKDmnGvJ485CwmfNchjHe5jWwqKepapmzUEj41yxIAqOg+C4LbXuJlkiO8A==", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regenerate-unicode-properties": "5.1.3", + "regjsgen": "0.3.0", + "regjsparser": "0.2.1", + "unicode-match-property-ecmascript": "1.0.3", + "unicode-match-property-value-ecmascript": "1.0.1" + } + }, + "regjsgen": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.3.0.tgz", + "integrity": "sha1-DuSj6SdkMM2iXx54nqbBW4ewy0M=", + "dev": true + }, + "regjsparser": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.2.1.tgz", + "integrity": "sha1-w3h1U/rwTndcMCEC7zRtmVAA7Bw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "require-package-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", + "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=", + "dev": true + }, + "require-resolve": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/require-resolve/-/require-resolve-0.0.2.tgz", + "integrity": "sha1-urQQqxruLz9Vt5MXRR3TQodk5vM=", + "dev": true, + "requires": { + "x-path": "0.0.2" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "requires": { + "commander": "2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": "1.0.1" + } + } + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=" + }, + "static-eval": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-0.2.4.tgz", + "integrity": "sha1-t9NNg4k3uWn5ZBygfUj47eJj6ns=", + "requires": { + "escodegen": "0.0.28" + }, + "dependencies": { + "escodegen": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.28.tgz", + "integrity": "sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=", + "requires": { + "esprima": "1.0.4", + "estraverse": "1.3.2", + "source-map": "0.1.43" + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + }, + "estraverse": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", + "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=" + } + } + }, + "static-module": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-1.5.0.tgz", + "integrity": "sha1-J9qYg8QajNCSNvhC8MHrxu32PYY=", + "requires": { + "concat-stream": "1.6.0", + "duplexer2": "0.0.2", + "escodegen": "1.3.3", + "falafel": "2.1.0", + "has": "1.0.1", + "object-inspect": "0.4.0", + "quote-stream": "0.0.0", + "readable-stream": "1.0.34", + "shallow-copy": "0.0.1", + "static-eval": "0.2.4", + "through2": "0.4.2" + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + } + } + }, + "stream-http": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "4.0.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "strip-outer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.0.tgz", + "integrity": "sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g=", + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "requires": { + "has-flag": "2.0.0" + } + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.4", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "tar-stream": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", + "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", + "requires": { + "bl": "1.2.1", + "end-of-stream": "1.4.0", + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + }, + "thunkify-wrap": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/thunkify-wrap/-/thunkify-wrap-1.0.4.tgz", + "integrity": "sha1-tSvlSN3+/aIOALWMYJZ2K0PdaIA=", + "requires": { + "enable": "1.3.2" + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "requires": { + "os-homedir": "1.0.2" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "timers-browserify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", + "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "toml": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.3.tgz", + "integrity": "sha512-O7L5hhSQHxuufWUdcTRPfuTh3phKfAZ/dqfxZFoxPCj2RYmpaSGLEIs016FCXItQwNr08yefUB5TSjzRYnajTA==" + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz", + "integrity": "sha512-N9IvkQslUGYGC24RkJk1ba99foK6TkwC2FHAEBlQFBP0RxQZS8ZpJuAZcwiY/w9ZJHFQb1aOXBI60OdxhTrwEQ==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typedarray-pool/-/typedarray-pool-1.1.0.tgz", + "integrity": "sha1-0RT0hIAUifU+yrXoCIqiMET0mNk=", + "requires": { + "bit-twiddle": "1.0.2", + "dup": "1.0.0" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "uid": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-0.0.2.tgz", + "integrity": "sha1-XkpdS3gTi09w+J/Tx2/FmqnS8QM=" + }, + "unbzip2-stream": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz", + "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==", + "requires": { + "buffer": "3.6.0", + "through": "2.3.8" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.3.tgz", + "integrity": "sha512-iG/2t0F2LAU8aZYPkX5gi7ebukHnr3sWFESpb+zPQeeaQwOkfoO6ZW17YX7MdRPNG9pCy+tjzGill+Ah0Em0HA==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.3.tgz", + "integrity": "sha512-nFcaBFcr08UQNF15ZgI5ISh3yUnQm7SJRRxwYrL5VYX46pS+6Q7TCTv4zbK+j6/l7rQt0mMiTL2zpmeygny6rA==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "1.0.3", + "unicode-property-aliases-ecmascript": "1.0.3" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.1.tgz", + "integrity": "sha512-lM8B0FDZQh9yYGgiabRQcyWicB27VLOolSBRIxsO7FeQPtg+79Oe7sC8Mzr8BObDs+G9CeYmC/shHo6OggNEog==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.3.tgz", + "integrity": "sha512-TdDmDOTxEf2ad1g3ZBpM6cqKIb2nJpVlz1Q++casDryKz18tpeMBhSng9hjC1CTQCkOV9Rw2knlSB6iRo7ad1w==", + "dev": true + }, + "union": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", + "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", + "dev": true, + "requires": { + "qs": "2.3.3" + }, + "dependencies": { + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "unyield": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/unyield/-/unyield-0.0.1.tgz", + "integrity": "sha1-FQ5l2kK/d0JEW5WKZOubhdHSsYA=", + "requires": { + "co": "3.1.0" + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-join": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.2.tgz", + "integrity": "sha1-wHJ1aWetJLi1nldBVRyqx49QuLc=", + "dev": true + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "requires": { + "os-homedir": "1.0.2" + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "requires": { + "builtins": "1.0.3" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "ware": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", + "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", + "requires": { + "wrap-fn": "0.1.5" + } + }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + } + }, + "webpack": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz", + "integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==", + "dev": true, + "requires": { + "acorn": "5.2.1", + "acorn-dynamic-import": "2.0.2", + "ajv": "5.5.1", + "ajv-keywords": "2.1.1", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "win-fork": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/win-fork/-/win-fork-1.1.1.tgz", + "integrity": "sha1-j1jgZW/KAK3IyGoriePNLWotXl4=" + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "wrap-fn": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", + "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", + "requires": { + "co": "3.1.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "x-path": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/x-path/-/x-path-0.0.2.tgz", + "integrity": "sha1-KU0Ha7l6dwbMBwu7Km/YxU32exI=", + "dev": true, + "requires": { + "path-extra": "1.0.3" + } + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + }, + "dependencies": { + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + } + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yaml-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/yaml-js/-/yaml-js-0.0.8.tgz", + "integrity": "sha1-h8+lqWE/SOJgBUINao7g2m/o2uw=" + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/keras-js/package.json b/keras-js/package.json new file mode 100644 index 0000000000..cef8b5db5e --- /dev/null +++ b/keras-js/package.json @@ -0,0 +1,91 @@ +{ + "name": "keras-js", + "version": "1.0.0", + "description": "A simple lib for keras on nodejs.", + "preferGlobal": true, + "main": "src/", + "repository": { + "type": "git", + "url": "git+https://github.com/vuejs/vue-cli.git" + }, + "keywords": [ + "vue", + "cli", + "spa" + ], + "author": "BL", + "license": "MIT", + "bugs": { + "url": "https://github.com/vuejs/vue-cli/issues" + }, + "homepage": "https://github.com/vuejs/vue-cli#readme", + "scripts": { + "build:browser": "rm -rf dist; NODE_ENV=production BABEL_ENV=browser webpack --config webpack.config.js", + "build:node": "rm -rf lib; NODE_ENV=production BABEL_ENV=node babel src --out-dir lib", + "build": "npm run build:browser && npm run build:node" + }, + "dependencies": { + "async": "^2.4.0", + "chalk": "^2.1.0", + "commander": "^2.9.0", + "consolidate": "^0.14.0", + "download-git-repo": "^1.0.1", + "handlebars": "^4.0.5", + "inquirer": "^3.3.0", + "metalsmith": "^2.1.0", + "minimatch": "^3.0.0", + "multimatch": "^2.1.0", + "ora": "^1.3.0", + "read-metadata": "^1.0.0", + "request": "^2.67.0", + "rimraf": "^2.5.0", + "semver": "^5.1.0", + "tildify": "^1.2.0", + "uid": "0.0.2", + "user-home": "^2.0.0", + "validate-npm-package-name": "^3.0.0", + "coffee-script": "1.12.7", + "axios": "^0.17.1", + "bluebird": "^3.5.1", + "cwise": "^1.0.10", + "lodash": "^4.17.4", + "ndarray": "^1.0.18", + "ndarray-blas-level2": "^1.1.0", + "ndarray-concat-rows": "^1.0.1", + "ndarray-gemm": "^1.0.0", + "ndarray-ops": "^1.2.2", + "ndarray-resample": "^1.0.1", + "ndarray-squeeze": "^1.0.2", + "ndarray-tile": "^1.0.3", + "ndarray-unpack": "^1.0.0", + "ndarray-unsqueeze": "^1.0.3", + "performance-now": "^2.1.0", + "protobufjs": "^6.8.1" + }, + "devDependencies": { + "@babel/cli": "7.0.0-beta.32", + "@babel/core": "7.0.0-beta.32", + "@babel/plugin-proposal-class-properties": "7.0.0-beta.32", + "@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.32", + "@babel/preset-env": "7.0.0-beta.32", + "babel-eslint": "^8.0.2", + "babel-loader": "8.0.0-beta.0", + "babel-plugin-inline-import": "^2.0.6", + "babel-plugin-lodash": "^3.3.2", + "chai": "^4.1.2", + "eslint": "^3.19.0", + "eslint-plugin-vue-libs": "^1.2.1", + "execa": "^0.8.0", + "http-server": "^0.10.0", + "mocha": "^3.5.3", + "webpack": "^3.8.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "directories": { + "doc": "docs", + "lib": "lib", + "test": "test" + } +} diff --git a/keras-js/src/Layer.js b/keras-js/src/Layer.js new file mode 100644 index 0000000000..697a280cfc --- /dev/null +++ b/keras-js/src/Layer.js @@ -0,0 +1,73 @@ +import { webgl2 } from './WebGL2' + +/** + * Layer class + */ +export default class Layer { + /** + * Creates a layer + * + * @param {Object} [attrs] - layer attributes + */ + constructor(attrs = {}) { + this.layerClass = 'Layer' + this.name = attrs.name + this.gpu = webgl2.isSupported && attrs.gpu + + this.params = [] + this.weights = {} + + this.inbound = [] + this.outbound = [] + } + + /** + * Throws Error, adding layer context info to message + * + * @param {string} message + */ + throwError(message) { + throw new Error(`[${this.layerClass} layer: ${this.name || ''}] ${message}`) + } + + /** + * Toggle GPU mode on/off + * + * @param {boolean} mode - on/off + */ + toggleGPU(mode) { + const newMode = typeof mode === 'undefined' ? !this.gpu : mode + if (webgl2.isSupported && newMode) { + this.gpu = true + } else { + this.gpu = false + } + } + + /** + * Set layer weights + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + * @param {boolean} createGLTexture + */ + setWeights(weightsArr, createGLTexture = true) { + this.params.forEach((p, i) => { + this.weights[p] = weightsArr[i] + + if (this.gpu && createGLTexture) { + this.weights[p].createGLTexture({ type: '2d', format: 'float' }) + } + }) + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + this.output = x + return this.output + } +} diff --git a/keras-js/src/Model.js b/keras-js/src/Model.js new file mode 100644 index 0000000000..63ded1d93b --- /dev/null +++ b/keras-js/src/Model.js @@ -0,0 +1,617 @@ +import Promise from 'bluebird' +import axios from 'axios' +import _ from 'lodash' +import now from 'performance-now' +import * as layers from './layers' +import * as visMethods from './visualizations' +import Tensor from './Tensor' +import { webgl2 } from './WebGL2' +import proto from './proto' + +const axiosSource = axios.CancelToken.source() + +/** + * Model class + */ +export default class Model { + /** + * Create new Model class + * + * @param {string} config.filepath - path to protobuf-serialized model definition file + * @param {Object} [config.headers] - any additional HTTP headers required for resource fetching + * @param {Object} [config.filesystem] - specifies that data files are from local file system (Node.js only) + * @param {boolean} [config.gpu] - enable GPU + * @param {boolean} [config.transferLayerOutputs] - in GPU mode, transfer outputs of each layer from GPU->CPU (warning: decreases performance) + * @param {boolean} [config.pauseAfterLayerCalls] - break up blocking computation by layer, to allow for intervening DOM updates, for example + * @param {string[]} [config.visualizations] - specifies which visualizations to calculate + */ + constructor(config = {}) { + const { + filepath = null, + headers = {}, + filesystem = false, + gpu = false, + transferLayerOutputs = false, + pauseAfterLayerCalls = false, + visualizations = [] + } = config + + if (!filepath) { + throw new Error('[Model] path to protobuf-serialized model definition file is missing.') + } + this.filepath = filepath + + // HTTP(S) headers used during data fetching + this.headers = headers + + // specifies that data files are from local file system (Node.js only) + this.filesystem = typeof window !== 'undefined' ? false : filesystem + + // data request progress + this.dataRequestProgress = 0 + + // Model config + this.id = null + this.name = null + this.kerasVersion = null + this.backend = null + this.modelConfig = {} + this.modelWeights = [] + + // flag to enable GPU where possible (disable in node environment) + this.gpu = typeof window !== 'undefined' && webgl2.isSupported ? gpu : false + + // in GPU mode, transfer intermediate outputs of each layer from GPU->CPU + this.transferLayerOutputs = transferLayerOutputs + + // break up blocking computation by layer, to allow for intervening DOM updates, for example + this.pauseAfterLayerCalls = pauseAfterLayerCalls + + // map of model layers + this.modelLayersMap = new Map() + + // map of input tensors + this.inputTensorsMap = new Map() + + // names of input and output layers + this.inputLayerNames = [] + this.outputLayerNames = [] + + // array of model layer names with finished output + this.finishedLayerNames = [] + + // flag while computations are being performed + this.isRunning = false + + // stats object for last `predict` call + this.predictStats = {} + + // visualizations to calculate + this.visMap = new Map() + visualizations.forEach(v => { + if (v in visMethods) { + const visInstance = new visMethods[v]({ modelLayersMap: this.modelLayersMap, gpu: this.gpu }) + this.visMap.set(v, visInstance) + } + }) + + // Promise for when Model class is initialized + this._ready = this._initialize() + } + + /** + * Checks whether WebGL 2 is supported by browser + */ + checkGPUSupport() { + return webgl2.isSupported + } + + /** + * Promise for when model data is loaded and layers are initialized. + * + * @returns {Promise} + */ + ready() { + return this._ready + } + + /** + * Cancels any existing data requests + */ + _interrupt() { + axiosSource.cancel() + } + + /** + * Model initialization + * + * @returns {Promise} + */ + async _initialize() { + try { + const req = this.filesystem ? this._dataRequestFS() : this._dataRequestHTTP(this.headers) + await req + } catch (err) { + console.log(err) + this._interrupt() + } + + // build directed acyclic graph + this._buildDAG() + + // run predict once with initial empty input tensors to cache variables such as shape inference + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name) + inputLayer.call(this.inputTensorsMap.get(name)) + inputLayer.hasOutput = true + inputLayer.visited = true + }) + await this._traverseDAG(this.inputLayerNames) + + // reset hasOutput and visited flags in all layers + this.finishedLayerNames = [] + this.modelLayersMap.forEach(layer => { + layer.hasOutput = false + layer.visited = false + }) + + // initialize visualizations + this.visMap.forEach(visInstance => { + visInstance.initialize() + }) + + return true + } + + /** + * Makes data HTTP request (browser or node) + * + * @param {Object} [headers] - any headers to be passed along with request + * @returns {Promise} + */ + async _dataRequestHTTP(headers = {}) { + try { + const res = await axios.get(this.filepath, { + responseType: 'arraybuffer', + headers, + onDownloadProgress: e => { + if (e.lengthComputable) { + const percentComplete = Math.round(100 * e.loaded / e.total) + this.dataRequestProgress = percentComplete + } + }, + cancelToken: axiosSource.token + }) + + this.decodeProtobuf(new Uint8Array(res.data)) + } catch (err) { + if (axios.isCancel(err)) { + console.log('[Model] Data request canceled', err.message) + } else { + throw err + } + } + + this.dataRequestProgress = 100 + } + + /** + * Makes data FS request (node only) + * + * @returns {Promise} + */ + async _dataRequestFS() { + const readFile = Promise.promisify(require('fs').readFile) + + try { + const file = await readFile(this.filepath) + this.decodeProtobuf(file) + } catch (err) { + throw err + } + + this.dataRequestProgress = 100 + } + + /** + * Verifies and decodes binary buffer representing protobuf-serialized model definition file. + * + * @param {Uint8Array|Buffer} buffer + */ + decodeProtobuf(buffer) { + const err = proto.Model.verify(buffer) + if (err) { + throw new Error(`[Model] Invalid model - check protobuf serialization: {err}`) + } + const model = proto.Model.decode(buffer) + this.id = model.id + this.name = model.name + this.kerasVersion = model.kerasVersion + this.backend = model.backend + this.modelConfig = JSON.parse(model.modelConfig) + this.modelWeights = model.modelWeights + } + + /** + * Loading progress calculated from all the data requests combined. + * @returns {number} + */ + getLoadingProgress() { + return this.dataRequestProgress + } + + /** + * Toggle GPU mode on/off + * Iterate through all layers and set `gpu` attribute + * @param {boolean} mode - on/off + */ + toggleGPU(mode) { + if (typeof mode === 'undefined') { + this.gpu = !this.gpu + } else { + this.gpu = mode + } + this.modelLayersMap.forEach(layer => { + layer.toggleGPU(this.gpu) + }) + this.visMap.forEach(visInstance => { + visInstance.gpu = this.gpu + }) + this.resetInputTensors() + } + + /** + * Resets input tensors + */ + resetInputTensors() { + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name) + this.inputTensorsMap.set(name, new Tensor([], inputLayer.shape)) + }) + } + + /** + * Builds directed acyclic graph of model layers + * + * Every layer in the model defines inbound and outbound nodes. For Keras models of class Sequential, we still convert + * the list into DAG format for straightforward interoperability with graph models (however, we must first create an + * Input layer as the initial layer. For class Model, the DAG is constructed from the configuration inbound and + * outbound nodes. Note that Models can have layers be entire Sequential branches. + */ + _buildDAG() { + const modelClass = this.modelConfig.class_name + + let modelConfig = [] + if (modelClass === 'Sequential') { + modelConfig = this.modelConfig.config + } else if (modelClass === 'Model') { + modelConfig = this.modelConfig.config.layers + } + + if (!(Array.isArray(modelConfig) && modelConfig.length)) { + throw new Error('[Model] Model configuration does not contain any layers.') + } + + modelConfig.forEach((layerDef, index) => { + const layerClass = layerDef.class_name + const layerConfig = layerDef.config + + if (modelClass === 'Model' && layerClass === 'Sequential') { + // when layer is a Sequential branch in a Model + layerConfig.forEach((branchLayerDef, branchIndex) => { + const branchLayerClass = branchLayerDef.class_name + const branchLayerConfig = branchLayerDef.config + + const branchInboundLayerNames = + branchIndex === 0 + ? layerDef.inbound_nodes[0].map(node => node[0]) + : [layerConfig[branchIndex - 1].config.name] + + this._createLayer(branchLayerClass, branchLayerConfig, branchInboundLayerNames) + }) + } else if (!(layerClass in layers)) { + throw new Error(`[Model] Layer ${layerClass} specified in model configuration is not implemented!`) + } else { + // create InputLayer node for Sequential class (which is not explicitly defined in config) + // create input tensor for InputLayer specified in Model class (layer itself created later) + if (modelClass === 'Sequential' && index === 0) { + const inputName = 'input' + const inputShape = layerConfig.batch_input_shape.slice(1) + const layer = new layers.InputLayer({ name: inputName, shape: inputShape, gpu: this.gpu }) + this.modelLayersMap.set(inputName, layer) + this.inputTensorsMap.set(inputName, new Tensor([], inputShape)) + this.inputLayerNames.push(inputName) + } else if (modelClass === 'Model' && layerClass === 'InputLayer') { + const inputShape = layerConfig.batch_input_shape.slice(1) + this.inputTensorsMap.set(layerConfig.name, new Tensor([], inputShape)) + this.inputLayerNames.push(layerConfig.name) + } + + let inboundLayerNames = [] + if (modelClass === 'Sequential') { + if (index === 0) { + inboundLayerNames = ['input'] + } else { + inboundLayerNames = [modelConfig[index - 1].config.name] + } + } else if (modelClass === 'Model') { + const inboundNodes = layerDef.inbound_nodes + if (inboundNodes && inboundNodes.length) { + inboundLayerNames = inboundNodes[0].map(node => node[0]) + } + } + this._createLayer(layerClass, layerConfig, inboundLayerNames) + } + }) + + this.modelLayersMap.forEach(layer => { + if (layer.outbound.length === 0) { + this.outputLayerNames.push(layer.name) + } + }) + + this.inputLayerNames.sort() + this.outputLayerNames.sort() + } + + /** + * Create single layer + * + * @param {Object} layerClass + * @param {Object} layerConfig + * @param {string[]} inboundLayerNames + */ + _createLayer(layerClass, layerConfig, inboundLayerNames) { + const layer = new layers[layerClass](Object.assign({}, layerConfig, { gpu: this.gpu })) + + // layer weights + let weightNames = [] + if (layerClass === 'Bidirectional') { + const forwardWeightNames = layer.forwardLayer.params.map( + param => `${layerConfig.name}/forward_${layerConfig.layer.config.name}/${param}` + ) + const backwardWeightNames = layer.backwardLayer.params.map( + param => `${layerConfig.name}/backward_${layerConfig.layer.config.name}/${param}` + ) + weightNames = forwardWeightNames.concat(backwardWeightNames) + } else if (layerClass === 'TimeDistributed') { + weightNames = layer.layer.params.map(param => `${layerConfig.name}/${param}`) + } else { + weightNames = layer.params.map(param => `${layerConfig.name}/${param}`) + } + + if (weightNames && weightNames.length) { + const weights = weightNames.map(weightName => { + const weightDef = _.find(this.modelWeights, w => { + const weightRE = new RegExp(`^${weightName}`) + return weightRE.test(w.weightName) + }) + + if (!weightDef) { + throw new Error(`[Model] error loading weights.`) + } + + const { data, shape, type } = weightDef + + // need to make a copy of underlying ArrayBuffer + const buf = new ArrayBuffer(data.byteLength) + const arr = new Uint8Array(buf) + arr.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength)) + + if (type === 'uint8') { + // weights are quantized + const { quantizeMin, quantizeMax } = weightDef + const unquantized = new Float32Array(arr) + for (let i = 0, len = unquantized.length; i < len; i++) { + unquantized[i] *= (quantizeMax - quantizeMin) / 255 + unquantized[i] += quantizeMin + } + return new Tensor(unquantized, shape) + } else { + return new Tensor(new Float32Array(buf), shape) + } + }) + + layer.setWeights(weights) + } + + this.modelLayersMap.set(layerConfig.name, layer) + + inboundLayerNames.forEach(layerName => { + this.modelLayersMap.get(layerConfig.name).inbound.push(layerName) + this.modelLayersMap.get(layerName).outbound.push(layerConfig.name) + }) + } + + /** + * Async function for recursively traversing the DAG + * Graph object is stored in `this.modelDAG`, keyed by layer name. + * Layers are retrieved from Map object `this.modelLayersMap`. + * + * @param {string[]} nodes - array of layer names + * @returns {Promise} + */ + async _traverseDAG(nodes) { + if (nodes.length === 0) { + // Stopping criterion: + // an output node will have 0 outbound nodes. + return true + } else if (nodes.length === 1) { + // Where computational logic lives for a given layer node + // - Makes sure outputs are available from inbound layer nodes + // - Keeps async function going until outputs are available from inbound layer nodes + // (important for merge layer nodes where multiple inbound nodes may complete asynchronously) + // - Runs computation for current layer node: .call() + // - Starts new async function for outbound nodes + const node = nodes[0] + const currentLayer = this.modelLayersMap.get(node) + + if (currentLayer.layerClass === 'InputLayer') { + this.finishedLayerNames.push(this.modelLayersMap.get(node).name) + } else { + const currentLayer = this.modelLayersMap.get(node) + if (currentLayer.visited) { + return false + } + + const inboundLayers = currentLayer.inbound.map(n => this.modelLayersMap.get(n)) + if (!_.every(_.map(inboundLayers, 'hasOutput'))) { + return false + } + + if (currentLayer.isMergeLayer) { + currentLayer.call(_.map(inboundLayers, 'output')) + } else { + currentLayer.call(inboundLayers[0].output) + } + + currentLayer.hasOutput = true + currentLayer.visited = true + this.finishedLayerNames.push(currentLayer.name) + + if (this.pauseAfterLayerCalls) { + await Promise.delay(0) + } + } + + await this._traverseDAG(currentLayer.outbound) + } else { + await Promise.all(nodes.map(node => this._traverseDAG([node]))) + } + } + + /** + * Transfer intermediate outputs if specified, only in GPU mode and if transferLayerOutputs is set to true + */ + _maybeTransferIntermediateOutputs() { + if (this.gpu && this.transferLayerOutputs) { + this.modelLayersMap.forEach(layer => { + if (layer.output && layer.output.glTexture) { + webgl2.bindOutputTexture(layer.output.glTexture, layer.output.glTextureShape) + layer.output.transferFromGLTexture() + if (layer.output.is2DReshaped) { + layer.output.reshapeFrom2D() + } + } + }) + } + } + + /** + * Load data to input layer nodes + * + * @param {Object} inputData - object where the keys are the named inputs of the model, + * and values the TypedArray numeric data + */ + loadData(inputData) { + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name) + this.inputTensorsMap.get(name).replaceTensorData(inputData[name]) + inputLayer.call(this.inputTensorsMap.get(name)) + inputLayer.hasOutput = true + inputLayer.visited = true + }) + } + + /** + * Predict + * + * @param {Object} inputData - object where the keys are the named inputs of the model, + * and values the TypedArray numeric data + * @returns {Promise} - outputData object where the keys are the named outputs of the model, + * and values the TypedArray numeric data + */ + async predict(inputData) { + this.isRunning = true + + if (!_.isEqual(_.keys(inputData).sort(), this.inputLayerNames)) { + this.isRunning = false + throw new Error( + '[Model] predict() must take an object where the keys are the named inputs of the model: ' + + JSON.stringify(this.inputLayerNames) + ) + } + if (!_.every(this.inputLayerNames, name => inputData[name] instanceof Float32Array)) { + this.isRunning = false + throw new Error('[Model] predict() must take an object where the values are the flattened data as Float32Array.') + } + + // reset hasOutput and visited flags in all layers + this.finishedLayerNames = [] + this.modelLayersMap.forEach(layer => { + layer.hasOutput = false + layer.visited = false + }) + + // load data to input tensors + let start = now() + this.loadData(inputData) + this.predictStats.loadData = now() - start + + // start traversing DAG at inputs + start = now() + await this._traverseDAG(this.inputLayerNames) + this.predictStats.forwardPass = now() - start + + // transfer intermediate outputs if specified + this._maybeTransferIntermediateOutputs() + + // outputs are layers with no outbound nodes + const modelClass = this.modelConfig.class_name + const outputData = {} + if (modelClass === 'Sequential') { + const outputLayer = this.modelLayersMap.get(this.outputLayerNames[0]) + outputData['output'] = outputLayer.output.tensor.data + } else if (modelClass === 'Model') { + this.outputLayerNames.forEach(layerName => { + const outputLayer = this.modelLayersMap.get(layerName) + outputData[layerName] = outputLayer.output.tensor.data + }) + } + + // update visualizations + start = now() + this.visMap.forEach(visInstance => { + visInstance.update() + }) + this.predictStats.visualizations = now() - start + + this.isRunning = false + return outputData + } + + /** + * Run computation on a specific layer + * + * @param {string} layerName + * @param {Tensor|Object} input - can be Tensor instance or ndarray object + */ + layerCall(layerName, input) { + if (!this.modelLayersMap.has(layerName)) return + + let x + if (input instanceof Tensor) { + x = input + } else { + x = new Tensor(input.data, input.shape) + } + const layer = this.modelLayersMap.get(layerName) + return layer.call(x) + } + + /** + * Cleanup - important for memory management + */ + cleanup() { + // delete references to WebGL textures and buffers to free up GPU memory + webgl2.clearRefs() + + // Maps must be manually cleared so that values may be garbage collected + this.modelLayersMap.clear() + this.inputTensorsMap.clear() + this.visMap.clear() + + // delete reference to model weights object + delete this.modelWeights + } +} diff --git a/keras-js/src/Tensor.js b/keras-js/src/Tensor.js new file mode 100644 index 0000000000..1bc454fe5a --- /dev/null +++ b/keras-js/src/Tensor.js @@ -0,0 +1,420 @@ +import { webgl2, MAX_TEXTURE_SIZE } from './WebGL2' +import * as tensorUtils from './utils/tensorUtils' +import ndarray from 'ndarray' +import ops from 'ndarray-ops' +import squeeze from 'ndarray-squeeze' + +/** + * Tensor class + */ +export default class Tensor { + /** + * Creates a tensor + * + * @param {(TypedArray|Array)} data + * @param {number[]} shape + * @param {Object} [options] + */ + constructor(data, shape, options = {}) { + this.arrayType = options.type || Float32Array + + if (data && data.length && (data instanceof this.arrayType || data instanceof Array)) { + tensorUtils.checkShape(data, shape) + if (data instanceof this.arrayType) { + this.tensor = ndarray(data, shape) + } else if (data instanceof Array) { + this.tensor = ndarray(new this.arrayType(data), shape) + } + } else if (!data.length && shape.length) { + // if shape present but data not provided, initialize with 0s + this.tensor = ndarray(new this.arrayType(shape.reduce((a, b) => a * b, 1)), shape) + } else { + this.tensor = ndarray(new this.arrayType([]), []) + } + } + + /** + * Creates WebGL2 texture + * + * Without args, defaults to gl.TEXTURE_2D and gl.R32F + * + * @param {string} [opts.type] + * @param {string} [opts.format] + * @param {boolean} [opts.supportsTextureFragments] + */ + createGLTexture({ type = '2d', format = 'float', supportsTextureFragments = false }) { + let shape = [] + if (this.tensor.shape.length === 1) { + shape = [1, this.tensor.shape[0]] + this.is1D = true + } else if (this.tensor.shape.length === 2) { + shape = this.tensor.shape + } else if (this.tensor.shape.length === 3 && (type === '2d_array' || type === '3d')) { + shape = this.tensor.shape + } else { + throw new Error('[Tensor] cannot create WebGL2 texture.') + } + + this.glTextureShape = shape + this.glTextureType = type + this.glTextureFormat = format + + if (type === '2d') { + if (this.glTextureShape[0] > MAX_TEXTURE_SIZE && supportsTextureFragments) { + this._create2DRowFragmentedGLTexture() + } else { + this._create2DGLTexture() + } + } else if (type === '2d_array' || type === '3d') { + this._create3DGLTexture() + } else { + throw new Error(`[Tensor] invalid type ${type}.`) + } + } + + /** + * Create 2D WebGL2 texture + */ + _create2DGLTexture() { + const gl = webgl2.context + const textureOptions = webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat) + const { textureTarget, textureInternalFormat, textureFormat, textureType } = textureOptions + + this.glTexture = gl.createTexture() + webgl2.storeRef('texture', this.glTexture) + gl.bindTexture(textureTarget, this.glTexture) + + const shape = this.glTextureShape + const data = this.tensor.data + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data) + + // clamp to edge + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) + // no interpolation + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST) + } + + /** + * For 2D WebGL2 texture with first dimension exceeding MAX_TEXTURE_SIZE, creates as array of 2D textures + */ + _create2DRowFragmentedGLTexture() { + const gl = webgl2.context + const textureOptions = webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat) + const { textureTarget, textureInternalFormat, textureFormat, textureType } = textureOptions + + this.glTextureFragments = [] + this.glTextureFragmentShape = [MAX_TEXTURE_SIZE, this.glTextureShape[1]] + const shape = this.glTextureFragmentShape + const numFragments = Math.ceil(this.glTextureShape[0] / MAX_TEXTURE_SIZE) + let offset = 0 + + for (let k = 0; k < numFragments; k++) { + const glTexture = gl.createTexture() + webgl2.storeRef('texture', glTexture) + gl.bindTexture(textureTarget, glTexture) + + // append 0s to last fragment + let data + if (k === numFragments - 1) { + data = new this.arrayType(shape[0] * shape[1]) + data.set(this.tensor.data.slice(offset, offset + shape[0] * shape[1]), 0) + } else { + data = this.tensor.data.slice(offset, offset + shape[0] * shape[1]) + } + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data) + + // clamp to edge + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) + // no interpolation + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST) + + this.glTextureFragments.push(glTexture) + offset += shape[0] * shape[1] + } + } + + /** + * Create 3D WebGL2 texture + */ + _create3DGLTexture() { + const gl = webgl2.context + const textureOptions = webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat) + const { textureTarget, textureInternalFormat, textureFormat, textureType } = textureOptions + + this.glTexture = gl.createTexture() + webgl2.storeRef('texture', this.glTexture) + gl.bindTexture(textureTarget, this.glTexture) + + const shape = this.glTextureShape + const data = tensorUtils.data3DLayoutForGL(this.arrayType, this.tensor, this.glTextureShape) + gl.texImage3D( + textureTarget, + 0, + textureInternalFormat, + shape[1], + shape[0], + shape[2], + 0, + textureFormat, + textureType, + data + ) + + // clamp to edge + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) + // no interpolation + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST) + } + + /** + * Converts an array of row-fragmented glTextureFragments into a single column-stacked texture + */ + convert2DRowFragmentedGLTextureToColStack() { + if (!this.glTextureFragments || !this.glTextureFragmentShape) { + throw new Error('[Tensor] no glTextureFragments available.') + } + + const gl = webgl2.context + const textureOptions = webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat) + const { textureTarget, textureInternalFormat, textureFormat, textureType } = textureOptions + + if (!this.glTextureFragmentsAsColStack) { + this.glTextureFragmentsAsColStack = gl.createTexture() + webgl2.storeRef('texture', this.glTextureFragmentsAsColStack) + gl.bindTexture(textureTarget, this.glTextureFragmentsAsColStack) + + const numFragments = this.glTextureFragments.length + this.glTextureFragmentsAsColStackShape = [ + this.glTextureFragmentShape[0], + this.glTextureFragmentShape[1] * numFragments + ] + + const shape = this.glTextureFragmentsAsColStackShape + const data = new this.arrayType(shape.reduce((a, b) => a * b, 1)) + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data) + + // clamp to edge + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) + // no interpolation + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST) + } else { + gl.bindTexture(textureTarget, this.glTextureFragmentsAsColStack) + } + + const fbo = gl.createFramebuffer() + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo) + this.glTextureFragments.forEach((texture, k) => { + gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0) + gl.copyTexSubImage2D( + textureTarget, + 0, + k * this.glTextureFragmentShape[1], + 0, + 0, + 0, + this.glTextureFragmentShape[1], + this.glTextureFragmentShape[0] + ) + }) + gl.deleteFramebuffer(fbo) + } + + /** + * Removes glTextureFragmentsAsColStack + */ + removeGLTextureFragmentsAsColStack() { + if (this.glTextureFragmentsAsColStack) { + const gl = webgl2.context + gl.deleteTexture(this.glTextureFragmentsAsColStack) + delete this.glTextureFragmentsAsColStack + delete this.glTextureFragmentsAsColStackShape + } + } + + /** + * Deletes WebGLTexture + */ + deleteGLTexture() { + const gl = webgl2.context + if (this.glTexture) { + gl.deleteTexture(this.glTexture) + delete this.glTexture + } + if (this.glTextureFragments) { + this.glTextureFragments.forEach(texture => { + gl.deleteTexture(texture) + }) + delete this.glTextureFragments + } + } + + /** + * Replaces data in the underlying ndarray, and the corresponding WebGLTexture if glTexture is present + * + * @param {number[]} data + */ + replaceTensorData(data) { + if (data && data.length && data instanceof this.arrayType) { + this.tensor.data.set(data) + } else if (data && data.length && data instanceof Array) { + this.tensor.data.set(new this.arrayType(data)) + } else { + throw new Error('[Tensor] invalid input for replaceTensorData method.') + } + + if (this.glTexture) { + const gl = webgl2.context + const textureOptions = webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat) + const { textureTarget, textureFormat, textureType } = textureOptions + gl.bindTexture(textureTarget, this.glTexture) + + const shape = this.glTextureShape + if (this.glTextureType === '2d') { + const data = this.tensor.data + gl.texSubImage2D(textureTarget, 0, 0, 0, shape[1], shape[0], textureFormat, textureType, data, 0) + } else if (this.glTextureType === '2d_array' || this.glTextureType === '3d') { + const data = tensorUtils.data3DLayoutForGL(this.arrayType, this.tensor, shape) + gl.texSubImage3D(textureTarget, 0, 0, 0, 0, shape[1], shape[0], shape[2], textureFormat, textureType, data, 0) + } + } + } + + /** + * Transfer data from webgl texture on GPU to ndarray on CPU + */ + transferFromGLTexture() { + if (this.glTextureFragments) { + this.tensor = ndarray(new this.arrayType(this.glTextureShape[0] * this.glTextureShape[1]), this.glTextureShape) + let offset = 0 + for (let k = 0; k < this.glTextureFragments.length; k++) { + webgl2.bindOutputTexture(this.glTextureFragments[k], this.glTextureFragmentShape) + const fragmentData = webgl2.readData(this.glTextureFragmentShape) + // last fragment may need to be truncated + if (k === this.glTextureFragments.length - 1) { + const truncate = this.tensor.data.length - offset + this.tensor.data.set(fragmentData.subarray(0, truncate), offset) + } else { + this.tensor.data.set(fragmentData, offset) + } + offset += fragmentData.length + } + } else { + webgl2.bindOutputTexture(this.glTexture, this.glTextureShape) + this.tensor = ndarray(new this.arrayType([]), this.glTextureShape) + this.tensor.data = webgl2.readData(this.glTextureShape) + } + + if (this.is1D && this.glTextureShape[0] === 1) { + // collapse to 1D + this.tensor = squeeze(this.tensor, [0]) + } + } + + /** + * Reshapes data into 2D representation preserving last axis (typically channel axis) + */ + reshapeTo2D() { + const axis = this.tensor.shape.length - 1 + const axisSize = this.tensor.shape[axis] + const otherAxes = this.tensor.shape.slice(0, axis) + const otherAxesSize = otherAxes.reduce((a, b) => a * b, 1) + + const reshaped = ndarray(new this.arrayType(otherAxesSize * axisSize), [otherAxesSize, axisSize]) + + const otherAxesData = ndarray(new this.arrayType(otherAxesSize), otherAxes) + const otherAxesDataRaveled = ndarray(new this.arrayType(otherAxesSize), [otherAxesSize]) + const axisSlices = Array(this.tensor.shape.length).fill(null) + for (let n = 0; n < axisSize; n++) { + axisSlices[axis] = n + ops.assign(otherAxesData, this.tensor.pick(...axisSlices)) + otherAxesDataRaveled.data = otherAxesData.data + ops.assign(reshaped.pick(null, n), otherAxesDataRaveled) + } + + this.originalShape = this.tensor.shape + this.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.tensor.shape, false, axis) + this.tensor = reshaped + this.is2DReshaped = true + } + + /** + * Reshapes tensor in 2D representation back to original + * + * Typically called at the end when data is read back from GPU + * + * @param {number} axis + */ + reshapeFrom2D(axis = -1) { + if (!this.is2DReshaped) { + throw new Error('[Tensor] not in reshaped 2D representation.') + } + if (!this.originalShape) { + throw new Error('[Tensor] does not contain originalShape.') + } + + if (axis < 0) { + axis = this.originalShape.length + axis + } + + // second axis is the channel, or common, axis + const channelDataSize = this.tensor.shape[0] + const channels = this.tensor.shape[1] + + const reshaped = ndarray(new this.arrayType(this.originalShape.reduce((a, b) => a * b, 1)), this.originalShape) + const channelDataRaveled = ndarray(new this.arrayType(channelDataSize), [channelDataSize]) + const unraveledChannelShape = [...this.originalShape.slice(0, axis), ...this.originalShape.slice(axis + 1)] + const unraveledChannel = ndarray( + new this.arrayType(unraveledChannelShape.reduce((a, b) => a * b, 1)), + unraveledChannelShape + ) + const axisSlices = Array(this.originalShape.length).fill(null) + for (let n = 0; n < channels; n++) { + ops.assign(channelDataRaveled, this.tensor.pick(null, n)) + unraveledChannel.data = channelDataRaveled.data + axisSlices[axis] = n + ops.assign(reshaped.pick(...axisSlices), unraveledChannel) + } + + this.tensor = reshaped + } + + /** + * Reshapes data into 2D square representation (underlying data remaining contiguous) + */ + reshapeTo2DSquare() { + const squareDim = Math.ceil(Math.sqrt(this.tensor.size)) + const reshaped = ndarray(new this.arrayType(squareDim ** 2), [squareDim, squareDim]) + reshaped.data.set(this.tensor.data) + + this.originalShape = this.tensor.shape + this.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.tensor.shape, true) + this.tensor = reshaped + this.is2DSquareReshaped = true + } + + /** + * Reshapes tensor in 2D square representation back to original (underlying data remains contiguous) + */ + reshapeFrom2DSquare() { + if (!this.is2DSquareReshaped) { + throw new Error('[Tensor] not in reshaped 2D square representation.') + } + if (!this.originalShape) { + throw new Error('[Tensor] does not contain originalShape.') + } + + const size = this.originalShape.reduce((a, b) => a * b, 1) + const reshaped = ndarray(new this.arrayType(size), this.originalShape) + reshaped.data.set(this.tensor.data.subarray(0, size)) + + this.tensor = reshaped + } +} diff --git a/keras-js/src/WebGL2.js b/keras-js/src/WebGL2.js new file mode 100644 index 0000000000..30d00e4736 --- /dev/null +++ b/keras-js/src/WebGL2.js @@ -0,0 +1,329 @@ +import vertexShaderSource from './webgl/vertexShader.glsl' + +class WebGL2 { + constructor() { + this.isSupported = false + + this.vertexShader = null + + if (typeof window !== 'undefined') { + this.canvas = document.createElement('canvas') + this.context = this.canvas.getContext('webgl2') + + const gl = this.context + if (gl) { + this.isSupported = true + gl.getExtension('EXT_color_buffer_float') + this.MAX_TEXTURE_SIZE = gl.getParameter(gl.MAX_TEXTURE_SIZE) + this.MAX_TEXTURE_IMAGE_UNITS = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) + this.init() + } else { + console.log('Unable to initialize WebGL2 -- your browser may not support it.') + } + } + + this._refs = { textures: [], buffers: [] } + } + + /** + * Intialization after WebGL2 detected. + */ + init() { + this.createCommonVertexShader() + } + + /** + * Creates and compiles passthrough vertex shader that we will attach + * to all our programs. + */ + createCommonVertexShader() { + const gl = this.context + + const vertexShader = gl.createShader(gl.VERTEX_SHADER) + gl.shaderSource(vertexShader, vertexShaderSource) + gl.compileShader(vertexShader) + + const success = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS) + if (!success) { + console.error(gl.getShaderInfoLog(vertexShader)) + gl.deleteShader(vertexShader) + this.isSupported = false + } + + this.vertexShader = vertexShader + } + + /** + * Compiles fragment shader from source and creates program from it, + * using our passthrough vertex shader. + * + * @param {string} source - fragment shader GLSL source code + * @returns {WebGLProgram} + */ + compileProgram(source) { + const gl = this.context + + // create and compile fragment shader + const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER) + gl.shaderSource(fragmentShader, source) + gl.compileShader(fragmentShader) + + let success = gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS) + if (!success) { + console.error(gl.getShaderInfoLog(fragmentShader)) + gl.deleteShader(fragmentShader) + this.isSupported = false + } + + // create program and attach compiled shaders + const program = gl.createProgram() + gl.attachShader(program, this.vertexShader) + gl.attachShader(program, fragmentShader) + gl.linkProgram(program) + + success = gl.getProgramParameter(program, gl.LINK_STATUS) + if (!success) { + console.error(gl.getProgramInfoLog(program)) + this.isSupported = false + } + + this.setupVertices(program) + return program + } + + /** + * Setup vertices + * + * @param {WebGLProgram} program + */ + setupVertices(program) { + const gl = this.context + + const position = gl.getAttribLocation(program, 'position') + const positionVertexObj = gl.createBuffer() + gl.bindBuffer(gl.ARRAY_BUFFER, positionVertexObj) + this.storeRef('buffer', positionVertexObj) + + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array([-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]), + gl.STATIC_DRAW + ) + gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0) + gl.enableVertexAttribArray(position) + + const texcoord = gl.getAttribLocation(program, 'texcoord') + const texcoordVertexObj = gl.createBuffer() + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordVertexObj) + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]), gl.STATIC_DRAW) + gl.vertexAttribPointer(texcoord, 2, gl.FLOAT, false, 0, 0) + gl.enableVertexAttribArray(texcoord) + this.storeRef('buffer', texcoordVertexObj) + + const indicesVertexObj = gl.createBuffer() + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesVertexObj) + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW) + this.storeRef('buffer', indicesVertexObj) + } + + /** + * Selects linked program as active program + * + * @param {WebGLProgram} program + */ + selectProgram(program) { + const gl = this.context + gl.useProgram(program) + } + + /** + * Bind uniforms within program + * + * @param {WebGLProgram} program + * @param {Object[]} uniforms + */ + bindUniforms(program, uniforms) { + const gl = this.context + + uniforms.forEach(({ value, type, name }) => { + const loc = gl.getUniformLocation(program, name) + if (type === 'float') { + gl.uniform1f(loc, value) + } else if (type === 'int' || type === 'bool') { + gl.uniform1i(loc, value) + } + }) + } + + /** + * Bind input textures within program, handling inputs that are fragmented + * + * @param {WebGLProgram} program + * @param {Object[]} inputs + * @param {number} [k] + */ + bindInputTextures(program, inputs, k) { + const gl = this.context + + inputs.forEach(({ input, name }, i) => { + gl.activeTexture(gl.TEXTURE0 + i) + if (input.glTextureFragments) { + if (input.glTextureFragmentsAsColStack) { + const { textureTarget } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat) + gl.bindTexture(textureTarget, input.glTextureFragmentsAsColStack) + } else { + const { textureTarget } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat) + gl.bindTexture(textureTarget, input.glTextureFragments[k]) + } + } else { + const { textureTarget } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat) + gl.bindTexture(textureTarget, input.glTexture) + } + gl.uniform1i(gl.getUniformLocation(program, name), i) + }) + } + + /** + * Bind output texture + * + * @param {WebGLTexture} outputTexture + * @param {number[]} shape + */ + bindOutputTexture(outputTexture, shape) { + const gl = this.context + + gl.viewport(0, 0, shape[1], shape[0]) + + this.framebuffer = this.framebuffer || gl.createFramebuffer() + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer) + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0) + } + + /** + * Runs fragment shader program, after binding output, inputs, and uniforms + * + * @param {WebGLProgram} options.program + * @param {Tensor} options.output + * @param {Object[]} options.inputs + * @param {Object[]} options.uniforms + */ + runProgram({ program, output, inputs, uniforms, supportsTextureFragments = false }) { + if (!program) throw new Error('[WebGL2] missing program') + if (!output) throw new Error('[WebGL2] missing output') + if (!inputs) throw new Error('[WebGL2] missing inputs') + + const gl = this.context + this.selectProgram(program) + if (uniforms && Array.isArray(uniforms)) { + this.bindUniforms(program, uniforms) + } + + if (output.glTextureFragments) { + if (!supportsTextureFragments) { + throw new Error('[WebGL2] program does not support texture fragments') + } + + const inputsWithFragments = inputs.filter( + obj => obj.input.glTextureFragments && !obj.input.glTextureFragmentsAsColStack + ) + const numFragments = output.glTextureFragments.length + if (inputsWithFragments.some(obj => obj.input.glTextureFragments.length !== numFragments)) { + throw new Error('[WebGL2] number of texture fragments in inputs and output do not match') + } + + for (let k = 0; k < numFragments; k++) { + this.bindOutputTexture(output.glTextureFragments[k], output.glTextureFragmentShape) + this.bindInputTextures(program, inputs, k) + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0) + } + } else { + this.bindOutputTexture(output.glTexture, output.glTextureShape) + this.bindInputTextures(program, inputs) + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0) + } + } + + /** + * Reads pixel data from framebuffer + * + * @param {number[]} shape + * @returns {Float32Array} + */ + readData(shape) { + const gl = this.context + const buf = new ArrayBuffer(shape[0] * shape[1] * 4 * 4) + const view = new Float32Array(buf) + gl.readPixels(0, 0, shape[1], shape[0], gl.RGBA, gl.FLOAT, view) + const out = [] + for (let i = 0; i < view.length; i += 4) { + out.push(view[i]) + } + return new Float32Array(out) + } + + /** + * Gets WebGLTexture options constants + */ + getWebGLTextureOptions(type, format) { + const gl = this.context + + const targetMap = { + '2d': gl.TEXTURE_2D, + '2d_array': gl.TEXTURE_2D_ARRAY, + '3d': gl.TEXTURE_3D + } + + const internalFormatMap = { + float: gl.R32F, + int: gl.R32I + } + + const formatMap = { + float: gl.RED, + int: gl.RED_INTEGER + } + + const typeMap = { + float: gl.FLOAT, + int: gl.INT + } + + const textureTarget = targetMap[type] + const textureInternalFormat = internalFormatMap[format] + const textureFormat = formatMap[format] + const textureType = typeMap[format] + + return { textureTarget, textureInternalFormat, textureFormat, textureType } + } + + /** + * Store reference to WebGL texture or buffer on class instance, useful for when we want to delete later + * + * @param {string} type + * @param {WebGLTexture|WebGLBuffer} obj + */ + storeRef(type, obj) { + if (type === 'texture') { + this._refs.textures.push(obj) + } else if (type === 'buffer') { + this._refs.buffers.push(obj) + } + } + + /** + * Deletes all stored references to WebGL textures and buffers + */ + clearRefs() { + const gl = this.context + this._refs.textures.forEach(texture => gl.deleteTexture(texture)) + this._refs.buffers.forEach(buffer => gl.deleteBuffer(buffer)) + this._refs = { textures: [], buffers: [] } + } +} + +const webgl2 = new WebGL2() +const MAX_TEXTURE_SIZE = webgl2.MAX_TEXTURE_SIZE +const MAX_TEXTURE_IMAGE_UNITS = webgl2.MAX_TEXTURE_IMAGE_UNITS + +export { webgl2, MAX_TEXTURE_SIZE, MAX_TEXTURE_IMAGE_UNITS } diff --git a/keras-js/src/activations/elu.glsl b/keras-js/src/activations/elu.glsl new file mode 100644 index 0000000000..228d0a6093 --- /dev/null +++ b/keras-js/src/activations/elu.glsl @@ -0,0 +1,12 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + float alpha = 1.0; + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + outColor = max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0); +} diff --git a/keras-js/src/activations/elu.js b/keras-js/src/activations/elu.js new file mode 100644 index 0000000000..6231857bb8 --- /dev/null +++ b/keras-js/src/activations/elu.js @@ -0,0 +1,19 @@ +import cwise from 'cwise' + +const _elu = cwise({ + args: ['array', 'scalar'], + body: function(_x, alpha) { + _x = Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1) + } +}) + +/** + * In-place operation: ELU activation function + * + * @param {Tensor} x + * @param {{alpha: number}} [opts] + */ +export default function elu(x, opts = {}) { + const { alpha = 1.0 } = opts + _elu(x.tensor, alpha) +} diff --git a/keras-js/src/activations/hard_sigmoid.glsl b/keras-js/src/activations/hard_sigmoid.glsl new file mode 100644 index 0000000000..5f8a803863 --- /dev/null +++ b/keras-js/src/activations/hard_sigmoid.glsl @@ -0,0 +1,14 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + v = v * 0.2 + 0.5; + v = max(v, 0.0); + v = min(v, 1.0); + outColor = v; +} diff --git a/keras-js/src/activations/hard_sigmoid.js b/keras-js/src/activations/hard_sigmoid.js new file mode 100644 index 0000000000..b124128fcf --- /dev/null +++ b/keras-js/src/activations/hard_sigmoid.js @@ -0,0 +1,24 @@ +import cwise from 'cwise' + +// Reference hard sigmoid with slope and shift values from theano, see +// https://github.com/Theano/Theano/blob/master/theano/tensor/nnet/sigm.py +const _hard_sigmoid = cwise({ + args: ['array'], + body: function(_x) { + _x = _x * 0.2 + 0.5 + if (_x <= 0) { + _x = 0 + } else if (_x >= 1) { + _x = 1 + } + } +}) + +/** + * In-place operation: hard sigmoid activation function + * + * @param {Tensor} x + */ +export default function hard_sigmoid(x) { + _hard_sigmoid(x.tensor) +} diff --git a/keras-js/src/activations/index.js b/keras-js/src/activations/index.js new file mode 100644 index 0000000000..bd012d2760 --- /dev/null +++ b/keras-js/src/activations/index.js @@ -0,0 +1,12 @@ +import softmax from './softmax' +import elu from './elu' +import selu from './selu' +import softplus from './softplus' +import softsign from './softsign' +import relu from './relu' +import tanh from './tanh' +import sigmoid from './sigmoid' +import hard_sigmoid from './hard_sigmoid' +import linear from './linear' + +export { softmax, elu, selu, softplus, softsign, relu, tanh, sigmoid, hard_sigmoid, linear } diff --git a/keras-js/src/activations/linear.glsl b/keras-js/src/activations/linear.glsl new file mode 100644 index 0000000000..71f346f986 --- /dev/null +++ b/keras-js/src/activations/linear.glsl @@ -0,0 +1,10 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + outColor = texture(x, vec2(outTex.x, outTex.y)); +} diff --git a/keras-js/src/activations/linear.js b/keras-js/src/activations/linear.js new file mode 100644 index 0000000000..18fed1f42d --- /dev/null +++ b/keras-js/src/activations/linear.js @@ -0,0 +1,8 @@ +/** + * In-place operation: linear activation function + * + * @param {Tensor} x + */ +export default function linear(x) { + return x +} diff --git a/keras-js/src/activations/programSources.js b/keras-js/src/activations/programSources.js new file mode 100644 index 0000000000..313a3be055 --- /dev/null +++ b/keras-js/src/activations/programSources.js @@ -0,0 +1,21 @@ +import softmaxProgramSource from './softmax.glsl' +import eluProgramSource from './elu.glsl' +import seluProgramSource from './selu.glsl' +import softplusProgramSource from './softplus.glsl' +import softsignProgramSource from './softsign.glsl' +import reluProgramSource from './relu.glsl' +import tanhProgramSource from './tanh.glsl' +import sigmoidProgramSource from './sigmoid.glsl' +import hardSigmoidProgramSource from './hard_sigmoid.glsl' +import linearProgramSource from './linear.glsl' + +export { softmaxProgramSource as softmax } +export { eluProgramSource as elu } +export { seluProgramSource as selu } +export { softplusProgramSource as softplus } +export { softsignProgramSource as softsign } +export { reluProgramSource as relu } +export { tanhProgramSource as tanh } +export { sigmoidProgramSource as sigmoid } +export { hardSigmoidProgramSource as hard_sigmoid } +export { linearProgramSource as linear } diff --git a/keras-js/src/activations/relu.glsl b/keras-js/src/activations/relu.glsl new file mode 100644 index 0000000000..362997878b --- /dev/null +++ b/keras-js/src/activations/relu.glsl @@ -0,0 +1,11 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + outColor = max(v, 0.0); +} diff --git a/keras-js/src/activations/relu.js b/keras-js/src/activations/relu.js new file mode 100644 index 0000000000..c5d0d05a60 --- /dev/null +++ b/keras-js/src/activations/relu.js @@ -0,0 +1,25 @@ +import ops from 'ndarray-ops' +import Tensor from '../Tensor' + +/** + * In-place operation: ReLU activation function + * + * @param {Tensor} x + * @param {{alpha: number, maxValue: number}} [opts] + */ +export default function relu(x, opts = {}) { + const { alpha = 0, maxValue = null } = opts + let neg + if (alpha !== 0) { + neg = new Tensor([], x.tensor.shape) + ops.mins(neg.tensor, x.tensor, 0) + ops.mulseq(neg.tensor, alpha) + } + ops.maxseq(x.tensor, 0) + if (maxValue) { + ops.minseq(x.tensor, maxValue) + } + if (neg) { + ops.addeq(x.tensor, neg.tensor) + } +} diff --git a/keras-js/src/activations/selu.glsl b/keras-js/src/activations/selu.glsl new file mode 100644 index 0000000000..1263ad6e06 --- /dev/null +++ b/keras-js/src/activations/selu.glsl @@ -0,0 +1,13 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + float alpha = 1.6732632423543772848170429916717; + float scale = 1.0507009873554804934193349852946; + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + outColor = scale * (max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0)); +} diff --git a/keras-js/src/activations/selu.js b/keras-js/src/activations/selu.js new file mode 100644 index 0000000000..4cd8d4181e --- /dev/null +++ b/keras-js/src/activations/selu.js @@ -0,0 +1,19 @@ +import cwise from 'cwise' + +const _selu = cwise({ + args: ['array', 'scalar'], + body: function(_x) { + const alpha = 1.6732632423543772848170429916717 + const scale = 1.0507009873554804934193349852946 + _x = scale * (Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1)) + } +}) + +/** + * In-place operation: SELU activation function + * + * @param {Tensor} x + */ +export default function selu(x) { + _selu(x.tensor) +} diff --git a/keras-js/src/activations/sigmoid.glsl b/keras-js/src/activations/sigmoid.glsl new file mode 100644 index 0000000000..3a3496cb0f --- /dev/null +++ b/keras-js/src/activations/sigmoid.glsl @@ -0,0 +1,10 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + outColor = 1.0 / (1.0 + exp(-1.0 * texture(x, vec2(outTex.x, outTex.y)))); +} diff --git a/keras-js/src/activations/sigmoid.js b/keras-js/src/activations/sigmoid.js new file mode 100644 index 0000000000..d77a75029a --- /dev/null +++ b/keras-js/src/activations/sigmoid.js @@ -0,0 +1,17 @@ +import cwise from 'cwise' + +const _sigmoid = cwise({ + args: ['array'], + body: function(_x) { + _x = 1 / (1 + Math.exp(-_x)) + } +}) + +/** + * In-place operation: sigmoid activation function + * + * @param {Tensor} x + */ +export default function sigmoid(x) { + _sigmoid(x.tensor) +} diff --git a/keras-js/src/activations/softmax.glsl b/keras-js/src/activations/softmax.glsl new file mode 100644 index 0000000000..c4adcd782d --- /dev/null +++ b/keras-js/src/activations/softmax.glsl @@ -0,0 +1,28 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(x, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + float maxval = 0.0; + for (int i = 0; i < int(size[0]); ++i) { + float val = texelFetch(x, ivec2(i, out_y), 0).r; + if (i == 0 || val > maxval) { + maxval = val; + } + } + + float sum = 0.0; + for (int i = 0; i < int(size[0]); ++i) { + float val = texelFetch(x, ivec2(i, out_y), 0).r; + sum += exp(val - maxval); + } + + outColor = exp(texture(x, vec2(outTex.x, outTex.y)) - maxval) / sum; +} diff --git a/keras-js/src/activations/softmax.js b/keras-js/src/activations/softmax.js new file mode 100644 index 0000000000..a2403464a2 --- /dev/null +++ b/keras-js/src/activations/softmax.js @@ -0,0 +1,26 @@ +import ops from 'ndarray-ops' + +/** + * In-place operation: softmax activation function + * + * @param {Tensor} x + */ +export default function softmax(x) { + if (x.tensor.shape.length === 1) { + const maxval = ops.sup(x.tensor) + ops.subseq(x.tensor, maxval) + ops.expeq(x.tensor) + const sum = ops.sum(x.tensor) + ops.divseq(x.tensor, sum) + } else if (x.tensor.shape.length === 2) { + for (let i = 0; i < x.tensor.shape[0]; i++) { + const maxval = ops.sup(x.tensor.pick(i, null)) + ops.subseq(x.tensor.pick(i, null), maxval) + ops.expeq(x.tensor.pick(i, null)) + const sum = ops.sum(x.tensor.pick(i, null)) + ops.divseq(x.tensor.pick(i, null), sum) + } + } else { + throw new Error(`[activations.softmax] tensor shape ${x.tensor.shape} not supported.`) + } +} diff --git a/keras-js/src/activations/softplus.glsl b/keras-js/src/activations/softplus.glsl new file mode 100644 index 0000000000..a46de74491 --- /dev/null +++ b/keras-js/src/activations/softplus.glsl @@ -0,0 +1,10 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + outColor = log(1.0 + exp(texture(x, vec2(outTex.x, outTex.y)))); +} diff --git a/keras-js/src/activations/softplus.js b/keras-js/src/activations/softplus.js new file mode 100644 index 0000000000..2b0bf6b870 --- /dev/null +++ b/keras-js/src/activations/softplus.js @@ -0,0 +1,17 @@ +import cwise from 'cwise' + +const _softplus = cwise({ + args: ['array'], + body: function(_x) { + _x = Math.log(Math.exp(_x) + 1) + } +}) + +/** + * In-place operation: softplus activation function + * + * @param {Tensor} x + */ +export default function softplus(x) { + _softplus(x.tensor) +} diff --git a/keras-js/src/activations/softsign.glsl b/keras-js/src/activations/softsign.glsl new file mode 100644 index 0000000000..6cd8f340b7 --- /dev/null +++ b/keras-js/src/activations/softsign.glsl @@ -0,0 +1,12 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + v /= 1.0 + abs(v); + outColor = v; +} diff --git a/keras-js/src/activations/softsign.js b/keras-js/src/activations/softsign.js new file mode 100644 index 0000000000..daea804123 --- /dev/null +++ b/keras-js/src/activations/softsign.js @@ -0,0 +1,17 @@ +import cwise from 'cwise' + +const _softsign = cwise({ + args: ['array'], + body: function(_x) { + _x /= 1 + Math.abs(_x) + } +}) + +/** + * In-place operation: softsign activation function + * + * @param {Tensor} x + */ +export default function softsign(x) { + _softsign(x.tensor) +} diff --git a/keras-js/src/activations/tanh.glsl b/keras-js/src/activations/tanh.glsl new file mode 100644 index 0000000000..e24d6d3a7e --- /dev/null +++ b/keras-js/src/activations/tanh.glsl @@ -0,0 +1,11 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + outColor = tanh(v); +} diff --git a/keras-js/src/activations/tanh.js b/keras-js/src/activations/tanh.js new file mode 100644 index 0000000000..66ce4d8db7 --- /dev/null +++ b/keras-js/src/activations/tanh.js @@ -0,0 +1,17 @@ +import cwise from 'cwise' + +const _tanh = cwise({ + args: ['array'], + body: function(_x) { + _x = Math.tanh(_x) + } +}) + +/** + * In-place operation: tanh activation function + * + * @param {Tensor} x + */ +export default function tanh(x) { + _tanh(x.tensor) +} diff --git a/keras-js/src/index.js b/keras-js/src/index.js new file mode 100644 index 0000000000..92c4f8db55 --- /dev/null +++ b/keras-js/src/index.js @@ -0,0 +1,11 @@ +import '@babel/polyfill' +import Model from './Model' +import Tensor from './Tensor' +import { webgl2 } from './WebGL2' +import * as activations from './activations' +import * as layers from './layers' +import * as testUtils from './utils/testUtils' + +const GPU_SUPPORT = webgl2.isSupported + +export { Model, Tensor, GPU_SUPPORT, activations, layers, testUtils } diff --git a/keras-js/src/layers/InputLayer.js b/keras-js/src/layers/InputLayer.js new file mode 100644 index 0000000000..8c28b19d78 --- /dev/null +++ b/keras-js/src/layers/InputLayer.js @@ -0,0 +1,82 @@ +import Layer from '../Layer' +import Tensor from '../Tensor' +import _ from 'lodash' + +/** + * InputLayer layer class + */ +export default class InputLayer extends Layer { + /** + * Creates an InputLayer layer + * + * @param {Object} [attrs] - layer attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'InputLayer' + + const { shape = [] } = attrs + + this.shape = attrs.batch_input_shape && attrs.batch_input_shape.length ? attrs.batch_input_shape.slice(1) : shape + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.inputShape = x.tensor.shape + if (!_.isEqual(this.inputShape, this.shape)) { + this.throwError(`input tensor shape ${x.tensor.shape} does not match specified shape ${this.shape}.`) + } + this.output = new Tensor(x.tensor.data, x.tensor.shape) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + this.inputShape = x.tensor.shape + } else { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + this.inputShape = x.tensor.shape + } + } + + if (!_.isEqual(this.inputShape, this.shape)) { + this.throwError(`input tensor shape ${x.tensor.shape} does not match specified shape ${this.shape}.`) + } + + if (!x.glTexture) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } else if (x.tensor.shape.length > 2) { + x.reshapeTo2D() + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + } + + this.output = x + } +} diff --git a/keras-js/src/layers/advanced_activations/ELU.glsl b/keras-js/src/layers/advanced_activations/ELU.glsl new file mode 100644 index 0000000000..7699a2ace4 --- /dev/null +++ b/keras-js/src/layers/advanced_activations/ELU.glsl @@ -0,0 +1,12 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform float alpha; +out vec4 outColor; + +void main() { + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + outColor = max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0); +} diff --git a/keras-js/src/layers/advanced_activations/ELU.js b/keras-js/src/layers/advanced_activations/ELU.js new file mode 100644 index 0000000000..5eab55203f --- /dev/null +++ b/keras-js/src/layers/advanced_activations/ELU.js @@ -0,0 +1,107 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import cwise from 'cwise' +import programSource from './ELU.glsl' + +/** + * ELU advanced activation layer class + */ +export default class ELU extends Layer { + /** + * Creates a ELU activation layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.alpha] - scale for the negative factor + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'ELU' + + const { alpha = 1.0 } = attrs + + this.alpha = alpha + + // GPU setup + if (this.gpu) { + this.program = webgl2.compileProgram(programSource) + } + } + + _compute = cwise({ + args: ['array', 'scalar'], + body: function(_x, alpha) { + _x = Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1) + } + }) + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.output = x + this._compute(this.output.tensor, this.alpha) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + + if (!this.output) { + this.output = new Tensor([], x.glTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + if (x.is1D) { + this.output.is1D = x.is1D + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped + } + this.output.originalShape = x.originalShape + this.output.indicesForReshaped = x.indicesForReshaped + } + } + + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ input: x, name: 'x' }], + uniforms: [{ value: this.alpha, type: 'float', name: 'alpha' }], + supportsTextureFragments: true + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/advanced_activations/LeakyReLU.glsl b/keras-js/src/layers/advanced_activations/LeakyReLU.glsl new file mode 100644 index 0000000000..27281fe31f --- /dev/null +++ b/keras-js/src/layers/advanced_activations/LeakyReLU.glsl @@ -0,0 +1,12 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform float alpha; +out vec4 outColor; + +void main() { + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + outColor = max(v, 0.0) + alpha * min(v, 0.0); +} diff --git a/keras-js/src/layers/advanced_activations/LeakyReLU.js b/keras-js/src/layers/advanced_activations/LeakyReLU.js new file mode 100644 index 0000000000..3a0e5c1f4e --- /dev/null +++ b/keras-js/src/layers/advanced_activations/LeakyReLU.js @@ -0,0 +1,100 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import { relu } from '../../activations' +import programSource from './LeakyReLU.glsl' + +/** + * LeakyReLU advanced activation layer class + */ +export default class LeakyReLU extends Layer { + /** + * Creates a LeakyReLU activation layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.alpha] - negative slope coefficient + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'LeakyReLU' + + const { alpha = 0.3 } = attrs + + this.alpha = alpha + + // GPU setup + if (this.gpu) { + this.program = webgl2.compileProgram(programSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.output = x + relu(this.output, { alpha: this.alpha }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + + if (!this.output) { + this.output = new Tensor([], x.glTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + if (x.is1D) { + this.output.is1D = x.is1D + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped + } + this.output.originalShape = x.originalShape + this.output.indicesForReshaped = x.indicesForReshaped + } + } + + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ input: x, name: 'x' }], + uniforms: [{ value: this.alpha, type: 'float', name: 'alpha' }], + supportsTextureFragments: true + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/advanced_activations/PReLU.glsl b/keras-js/src/layers/advanced_activations/PReLU.glsl new file mode 100644 index 0000000000..d700443fc5 --- /dev/null +++ b/keras-js/src/layers/advanced_activations/PReLU.glsl @@ -0,0 +1,13 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform sampler2D alpha; +out vec4 outColor; + +void main() { + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + vec4 a = texture(alpha, vec2(outTex.x, outTex.y)); + outColor = max(v, 0.0) + a * min(v, 0.0); +} diff --git a/keras-js/src/layers/advanced_activations/PReLU.js b/keras-js/src/layers/advanced_activations/PReLU.js new file mode 100644 index 0000000000..9792e78cc8 --- /dev/null +++ b/keras-js/src/layers/advanced_activations/PReLU.js @@ -0,0 +1,111 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import cwise from 'cwise' +import programSource from './PReLU.glsl' + +/** + * PReLU advanced activation layer class + * + * reference code: + * ``` + * pos = K.relu(x) + * neg = self.alpha * (x - abs(x)) * 0.5 + * return pos + neg + * ``` + */ +export default class PReLU extends Layer { + /** + * Creates a PReLU activation layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'PReLU' + + // Layer weights specification + this.params = ['alpha'] + + // GPU setup + if (this.gpu) { + this.program = webgl2.compileProgram(programSource) + } + } + + _compute = cwise({ + args: ['array', 'array'], + body: function(_x, alpha) { + _x = Math.max(_x, 0) + alpha * Math.min(_x, 0) + } + }) + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.output = x + this._compute(this.output.tensor, this.weights['alpha'].tensor) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + + if (!this.output) { + this.output = new Tensor([], x.glTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + if (x.is1D) { + this.output.is1D = x.is1D + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped + } + this.output.originalShape = x.originalShape + this.output.indicesForReshaped = x.indicesForReshaped + } + } + + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.weights['alpha'], name: 'alpha' }], + supportsTextureFragments: true + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/advanced_activations/ThresholdedReLU.glsl b/keras-js/src/layers/advanced_activations/ThresholdedReLU.glsl new file mode 100644 index 0000000000..af6527f8b1 --- /dev/null +++ b/keras-js/src/layers/advanced_activations/ThresholdedReLU.glsl @@ -0,0 +1,12 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform float theta; +out vec4 outColor; + +void main() { + vec4 v = texture(x, vec2(outTex.x, outTex.y)); + outColor = v * float(greaterThan(v, vec4(theta))); +} diff --git a/keras-js/src/layers/advanced_activations/ThresholdedReLU.js b/keras-js/src/layers/advanced_activations/ThresholdedReLU.js new file mode 100644 index 0000000000..cdd4ad36e0 --- /dev/null +++ b/keras-js/src/layers/advanced_activations/ThresholdedReLU.js @@ -0,0 +1,107 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import cwise from 'cwise' +import programSource from './ThresholdedReLU.glsl' + +/** + * ThresholdedReLU advanced activation layer class + */ +export default class ThresholdedReLU extends Layer { + /** + * Creates a ThresholdedReLU activation layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.theta] - float >= 0. Threshold location of activation. + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'ThresholdedReLU' + + const { theta = 1 } = attrs + + this.theta = theta + + // GPU setup + if (this.gpu) { + this.program = webgl2.compileProgram(programSource) + } + } + + _compute = cwise({ + args: ['array', 'scalar'], + body: function(_x, theta) { + _x = _x * Number(_x > theta) + } + }) + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.output = x + this._compute(this.output.tensor, this.theta) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + + if (!this.output) { + this.output = new Tensor([], x.glTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + if (x.is1D) { + this.output.is1D = x.is1D + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped + } + this.output.originalShape = x.originalShape + this.output.indicesForReshaped = x.indicesForReshaped + } + } + + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ input: x, name: 'x' }], + uniforms: [{ value: this.theta, type: 'float', name: 'theta' }], + supportsTextureFragments: true + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/advanced_activations/index.js b/keras-js/src/layers/advanced_activations/index.js new file mode 100644 index 0000000000..bf1ba23885 --- /dev/null +++ b/keras-js/src/layers/advanced_activations/index.js @@ -0,0 +1,6 @@ +import LeakyReLU from './LeakyReLU' +import PReLU from './PReLU' +import ELU from './ELU' +import ThresholdedReLU from './ThresholdedReLU' + +export { LeakyReLU, PReLU, ELU, ThresholdedReLU } diff --git a/keras-js/src/layers/convolutional/Conv1D.js b/keras-js/src/layers/convolutional/Conv1D.js new file mode 100644 index 0000000000..f27cc1a2c5 --- /dev/null +++ b/keras-js/src/layers/convolutional/Conv1D.js @@ -0,0 +1,132 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import Conv2D from './Conv2D' +import * as tensorUtils from '../../utils/tensorUtils' +import ops from 'ndarray-ops' +import squeeze from 'ndarray-squeeze' +import unsqueeze from 'ndarray-unsqueeze' + +/** + * Conv1D layer class + */ +export default class Conv1D extends Layer { + /** + * Creates a Conv1D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.filters] - Number of convolution filters to use + * @param {number} [attrs.kernel_size] - Length of 1D convolution kernel + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Conv1D' + + const { + filters = 1, + kernel_size = 1, + strides = 1, + padding = 'valid', + dilation_rate = 1, + activation = 'linear', + use_bias = true + } = attrs + + if (padding !== 'valid' && padding !== 'same') { + this.throwError('Invalid padding.') + } + + if (dilation_rate !== 1 && strides !== 1) { + // Currently, specifying any dilation_rate value != 1 is incompatible with specifying any stride value != 1 + // https://keras.io/layers/convolutional/#conv1d + this.throwError('Incompatible combination of dilation_rate with strides.') + } + + this.use_bias = use_bias + + // Layer weights specification + this.params = this.use_bias ? ['kernel', 'bias'] : ['kernel'] + + // Bootstrap Conv2D layer: + // Conv1D is actually a shim on top of Conv2D, where + // all of the computational action is performed + // Note that we use `channels_first` dim ordering here. + const conv2dAttrs = { + filters, + kernel_size: [kernel_size, 1], + strides: [strides, 1], + padding, + data_format: 'channels_first', + dilation_rate, + activation, + use_bias + } + this._conv2dAttrs = conv2dAttrs + this._conv2d = new Conv2D(Object.assign(conv2dAttrs, { gpu: attrs.gpu })) + } + + /** + * Method for setting layer weights + * + * Override `super` method since weights must be set in `this._conv2d` + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + weightsArr[0].tensor = unsqueeze(weightsArr[0].tensor).transpose(2, 1, 0, 3) + this._conv2d.setWeights(weightsArr) + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + const input = new Tensor(x.tensor.data, x.tensor.shape) + input.tensor = unsqueeze(input.tensor).transpose(0, 2, 1) + const conv2dOutput = this._conv2d.call(input) + this.outputShape = [0, 2].map(i => this._conv2d.outputShape[i]) + this.output = new Tensor([], this.outputShape) + ops.assign(this.output.tensor, squeeze(conv2dOutput.tensor).transpose(1, 0, 2)) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + const inputShape = x.tensor.shape + const input = new Tensor([], inputShape) + Object.assign(input, x) + input.glTextureShape = inputShape + input.is2DReshaped = true + input.originalShape = [inputShape[0], 1, inputShape[1]] + input.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(input.originalShape, false, -1) + + this.output = this._conv2d.call(input) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/convolutional/Conv2D.js b/keras-js/src/layers/convolutional/Conv2D.js new file mode 100644 index 0000000000..553c97e5c2 --- /dev/null +++ b/keras-js/src/layers/convolutional/Conv2D.js @@ -0,0 +1,487 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import * as activations from '../../activations' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import * as tensorUtils from '../../utils/tensorUtils' +import ops from 'ndarray-ops' +import gemm from 'ndarray-gemm' +import mapInputProgramSource from '../../webgl/mapInput.glsl' +import mapInputFragmentsProgramSource from '../../webgl/mapInput.fragments.glsl' +import matMulProgramSource from '../../webgl/matMul.glsl' +import * as activationProgramSources from '../../activations/programSources' + +/** + * Conv2D layer class + */ +export default class Conv2D extends Layer { + /** + * Creates a Conv2D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.filters] - Number of convolution filters to use + * @param {number|number[]} [attrs.kernel_size] - Size of the convolution kernel + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Conv2D' + + const { + filters = 1, + kernel_size = [3, 3], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + dilation_rate = [1, 1], + activation = 'linear', + use_bias = true + } = attrs + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size] + } else { + this.kernelShape = [filters, kernel_size, kernel_size] + } + + if (Array.isArray(strides)) { + this.strides = strides + } else { + this.strides = [strides, strides] + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding + } else { + this.throwError('Invalid padding.') + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.') + } + + if (Array.isArray(dilation_rate)) { + this.dilationRate = dilation_rate + } else { + this.dilationRate = [dilation_rate, dilation_rate] + } + if ( + (this.dilationRate[0] !== 1 || this.dilationRate[1] !== 1) && + (this.strides[0] !== 1 || this.strides[1] !== 1) + ) { + // Currently, specifying any dilation_rate value != 1 is incompatible with specifying any stride value != 1 + // https://keras.io/layers/convolutional/#conv2d + this.throwError(`Incompatible combination of dilation_rate with strides.`) + } + + this.activation = activation + this.activationFunc = activations[activation] + + this.useBias = use_bias + + // Layer weights specification + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel'] + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + this.mapInputFragmentsProgram = webgl2.compileProgram(mapInputFragmentsProgramSource) + this.matMulProgram = webgl2.compileProgram(matMulProgramSource) + this.activationProgram = webgl2.compileProgram(activationProgramSources[this.activation]) + } + } + + /** + * Method for setting layer weights. Extends `super` method. + * + * W weight tensor is converted to `channels_last` mode if in `channels_first` mode. + * + * In `channels_last` mode, W weight tensor has shape [nbRow, nbCol, inputChannels, nbFilter] + * + * In `channels_first` mode, W weight tensor has shape [nbFilter, inputChannels, nbRow, nbCol] + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0) + } + super.setWeights(weightsArr, false) + + this._w2row() + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat + this.weights['kernel'].createGLTexture({ type: '2d', format: 'float' }) + if (this.useBias) { + this.weights['bias'].createGLTexture({ type: '2d', format: 'float' }) + } + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * Method for computing output dimensions and padding, based on input dimensions, kernel size, and padding mode. + * + * For tensorflow implementation of padding, see: + * https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/common_shape_fns.cc + * + * @param {number[]} inputShape + */ + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return + } + + const inputRows = inputShape[0] + const inputCols = inputShape[1] + const [nbFilter, nbRow, nbCol] = this.kernelShape + + // effective shape after filter dilation + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1) + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1) + + const outputRows = + this.padding === 'same' + ? Math.floor((inputRows + this.strides[0] - 1) / this.strides[0]) + : Math.floor((inputRows - nbRowDilated + this.strides[0]) / this.strides[0]) + const outputCols = + this.padding === 'same' + ? Math.floor((inputCols + this.strides[1] - 1) / this.strides[1]) + : Math.floor((inputCols - nbColDilated + this.strides[1]) / this.strides[1]) + const outputChannels = nbFilter + + const paddingRow = + this.padding === 'same' + ? Math.max(0, Math.floor((outputRows - 1) * this.strides[0] + nbRowDilated - inputRows)) + : 0 + const paddingCol = + this.padding === 'same' + ? Math.max(0, Math.floor((outputCols - 1) * this.strides[1] + nbColDilated - inputCols)) + : 0 + const paddingRowBefore = Math.floor(paddingRow / 2) + const paddingRowAfter = paddingRow - paddingRowBefore + const paddingColBefore = Math.floor(paddingCol / 2) + const paddingColAfter = paddingCol - paddingColBefore + + this.outputShape = [outputRows, outputCols, outputChannels] + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] + } + + /** + * Pad input tensor if necessary, for padding='same'. See above for notes on calculating padding. + * + * @param {Tensor} x + * @param {number} [padValue] + * @returns {Tensor} + */ + _padInput(x, padValue = 0) { + if (this.padding === 'same') { + const [inputRows, inputCols, inputChannels] = x.tensor.shape + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding + const newRows = inputRows + paddingRowBefore + paddingRowAfter + const newCols = inputCols + paddingColBefore + paddingColAfter + const _x = new Tensor([], [newRows, newCols, inputChannels]) + if (padValue !== 0) { + ops.assigns(_x.tensor, padValue) + } + ops.assign( + _x.tensor + .hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels) + .lo(paddingRowBefore, paddingColBefore, 0), + x.tensor + ) + return _x + } + return x + } + + /** + * Convert input tensor to column matrix + * + * @param {Tensor} x + * @returns {Tensor} + */ + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape + const nbRow = this.kernelShape[1] + const nbCol = this.kernelShape[2] + const outputRows = this.outputShape[0] + const outputCols = this.outputShape[1] + const nbPatches = outputRows * outputCols + const patchLen = nbRow * nbCol * inputChannels + + // effective shape after filter dilation + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1) + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1) + + if (!this.imColsMat) { + this.imColsMat = new Tensor([], [nbPatches, patchLen]) + } + + if (nbRowDilated === 1 && nbColDilated === 1 && this.strides[0] === 1 && this.strides[1] === 1) { + this.imColsMat.replaceTensorData(x.tensor.data) + return this.imColsMat + } + + const patch = new Tensor([], [nbRow, nbCol, inputChannels]) + let offset = 0 + for (let i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbColDilated; j <= limit; j += this.strides[1]) { + ops.assign( + patch.tensor, + x.tensor + .hi(i + nbRowDilated, j + nbColDilated, inputChannels) + .lo(i, j, 0) + .step(this.dilationRate[0], this.dilationRate[1], 1) + ) + this.imColsMat.tensor.data.set(patch.tensor.data, offset) + offset += patchLen + } + } + + return this.imColsMat + } + + /** + * Convert filter weights to row matrix + * + * @returns {Tensor} + */ + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[2] + const [nbFilter, nbRow, nbCol] = this.kernelShape + const patchLen = nbRow * nbCol * inputChannels + + this.wRowsMat = new Tensor([], [patchLen, nbFilter]) + + const patch = new Tensor([], [nbRow, nbCol, inputChannels]) + const patchRaveled = new Tensor([], [patchLen]) + for (let n = 0; n < nbFilter; n++) { + ops.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, null, n)) + patchRaveled.replaceTensorData(patch.tensor.data) + ops.assign(this.wRowsMat.tensor.pick(null, n), patchRaveled.tensor) + } + + return this.wRowsMat + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.inputShape = x.tensor.shape + this._calcOutputShape(this.inputShape) + x = this._padInput(x) + this._im2col(x) + + const nbFilter = this.kernelShape[0] + const outputRows = this.outputShape[0] + const outputCols = this.outputShape[1] + const nbPatches = outputRows * outputCols + const matMul = new Tensor([], [nbPatches, nbFilter]) + + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + ops.assigns(matMul.tensor.pick(null, n), this.weights['bias'].tensor.get(n)) + } + } + gemm(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1) + + this.output = new Tensor([], this.outputShape) + + let outputChannelRaveled = new Tensor([], [outputRows * outputCols]) + let outputChannel = new Tensor([], [outputRows, outputCols]) + for (let n = 0; n < nbFilter; n++) { + ops.assign(outputChannelRaveled.tensor, matMul.tensor.pick(null, n)) + outputChannel.replaceTensorData(outputChannelRaveled.tensor.data) + ops.assign(this.output.tensor.pick(null, null, n), outputChannel.tensor) + } + + this.activationFunc(this.output) + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + + /** + * Creates a index mapping from the 2D-reshaped input tensor with associated 3D tensor shape to the representation + * required prior to the matrix multiply. This allows us to work directly on the 2D tensor representations rather + * than needing to reshape to the 3D reprentation and calling im2col. + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return + } + + let [inputRows, inputCols, inputChannels] = this.inputShape + + let indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + // padding for border mode 'same' + if (this.padding === 'same') { + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding + inputRows = inputRows + paddingRowBefore + paddingRowAfter + inputCols = inputCols + paddingColBefore + paddingColAfter + const padValue = -1 + indices = this._padInput(indices, padValue) + } + + const nbRow = this.kernelShape[1] + const nbCol = this.kernelShape[2] + const outputRows = this.outputShape[0] + const outputCols = this.outputShape[1] + const nbPatches = outputRows * outputCols + const patchLen = nbRow * nbCol * inputChannels + + // effective shape after filter dilation + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1) + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1) + + this.indexMap = new Tensor([], [nbPatches, patchLen], { type: Int32Array }) + + const indicesPatch = new Tensor([], [nbRow, nbCol, inputChannels]) + let offset = 0 + for (let i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbColDilated; j <= limit; j += this.strides[1]) { + ops.assign( + indicesPatch.tensor, + indices.tensor + .hi(i + nbRowDilated, j + nbColDilated, inputChannels) + .lo(i, j, 0) + .step(this.dilationRate[0], this.dilationRate[1], 1) + ) + this.indexMap.tensor.data.set(indicesPatch.tensor.data, offset) + offset += patchLen + } + } + + this.indexMap.createGLTexture({ type: '2d', format: 'int', supportsTextureFragments: true }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + let outputTextureShape + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + this._calcOutputShape(this.inputShape) + this._createIndexMap(x.indicesForReshaped) + outputTextureShape = [this.indexMap.glTextureShape[0], this.weights['kernel'].glTextureShape[1]] + } else { + this.inputShape = x.tensor.shape + this._calcOutputShape(this.inputShape) + x = this._padInput(x) + this._im2col(x) + this.imColsMat.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + outputTextureShape = [this.imColsMat.glTextureShape[0], this.weights['kernel'].glTextureShape[1]] + } + + // create output textures if doesn't already exist + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new Tensor([], outputTextureShape) + this.outputPreactiv.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.outputPreactiv.is2DReshaped = true + this.outputPreactiv.originalShape = this.outputShape + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + if (!this.output) { + this.output = new Tensor([], outputTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.output.is2DReshaped = true + this.output.originalShape = this.outputShape + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + + if (x.is2DReshaped || x.is2DSquareReshaped) { + // run conv2d program, which involves mapping the input using indexMap, and matrix multiply with weights + const hasFragments = Boolean(x.glTextureFragments) + if (hasFragments) { + x.convert2DRowFragmentedGLTextureToColStack() + } + if (!this.convProgram) { + const convProgramSource = createGLSLProgram( + 'conv2d', + this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, + x.glTextureFragmentShape ? x.glTextureFragmentShape : x.glTextureShape, + this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, + this.useBias, + hasFragments + ) + this.convProgram = webgl2.compileProgram(convProgramSource) + } + webgl2.runProgram({ + program: this.convProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [ + { input: x, name: 'x' }, + { input: this.indexMap, name: 'indexMap' }, + { input: this.weights['kernel'], name: 'kernel' }, + ...(this.useBias ? [{ input: this.weights['bias'], name: 'bias' }] : []) + ], + supportsTextureFragments: true + }) + if (hasFragments) { + x.removeGLTextureFragmentsAsColStack() + } + } else { + // run matrix multiply on result of im2col + const matMulInputs = [{ input: this.imColsMat, name: 'A' }, { input: this.weights['kernel'], name: 'B' }] + if (this.useBias) { + matMulInputs.push({ input: this.weights['bias'], name: 'C' }) + } + webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ value: this.useBias ? 1 : 0, type: 'bool', name: 'addC' }], + supportsTextureFragments: true + }) + } + + // Activation + if (this.activation !== 'linear') { + webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ input: this.outputPreactiv, name: 'x' }], + supportsTextureFragments: true + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2D() + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + } +} diff --git a/keras-js/src/layers/convolutional/Conv2DTranspose.js b/keras-js/src/layers/convolutional/Conv2DTranspose.js new file mode 100644 index 0000000000..29e7b90014 --- /dev/null +++ b/keras-js/src/layers/convolutional/Conv2DTranspose.js @@ -0,0 +1,509 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import * as activations from '../../activations' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import * as tensorUtils from '../../utils/tensorUtils' +import cwise from 'cwise' +import ops from 'ndarray-ops' +import gemm from 'ndarray-gemm' +import matMulProgramSource from '../../webgl/matMul.glsl' +import * as activationProgramSources from '../../activations/programSources' + +const assignToRowIndicesMap = cwise({ + args: [{ blockIndices: -1 }, 'scalar', 'scalar'], + body: function(x, rowIndex, size) { + for (let i = 0; i < size; i++) { + if (x[i] === -1) { + x[i] = rowIndex + break + } + } + } +}) + +const assignToColIndicesMap = cwise({ + args: [{ blockIndices: -1 }, 'array', 'scalar'], + body: function(x, colIndex, size) { + for (let i = 0; i < size; i++) { + if (x[i] === -1) { + x[i] = colIndex + break + } + } + } +}) + +/** + * Conv2DTranspose layer class + */ +export default class Conv2DTranspose extends Layer { + /** + * Creates a Conv2DTranspose layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.filters] - Number of convolution filters to use. + * @param {number|number[]} [attrs.kernel_size] - Size of the convolution kernel. + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Conv2DTranspose' + + const { + filters = 1, + kernel_size = [3, 3], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + activation = 'linear', + use_bias = true + } = attrs + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size] + } else { + this.kernelShape = [filters, kernel_size, kernel_size] + } + + if (Array.isArray(strides)) { + this.strides = strides + } else { + this.strides = [strides, strides] + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding + } else { + this.throwError('Invalid padding.') + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.') + } + + this.activation = activation + this.activationFunc = activations[activation] + + this.useBias = use_bias + + // Layer weights specification + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel'] + + // GPU setup + if (this.gpu) { + this.matMulProgram = webgl2.compileProgram(matMulProgramSource) + this.activationProgram = webgl2.compileProgram(activationProgramSources[this.activation]) + } + } + + /** + * Method for setting layer weights. Extends `super` method. + * + * W weight tensor is converted to `channels_last` mode if in `channels_first` mode. + * + * In `channels_last` mode, W weight tensor has shape [nbRow, nbCol, inputChannels, nbFilter] + * + * In `channels_first` mode, W weight tensor has shape [nbFilter, inputChannels, nbRow, nbCol] + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0) + } + super.setWeights(weightsArr, false) + + this._w2row() + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat + this.weights['kernel'].createGLTexture({ type: '2d', format: 'float' }) + if (this.useBias) { + this.weights['bias'].createGLTexture({ type: '2d', format: 'float' }) + } + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * Method for computing output dimensions and padding, based on input dimensions, kernel size, and padding mode. + * + * For tensorflow implementation of padding, see: + * https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/common_shape_fns.cc + * + * For deconvolution, we will "take away" padding from the output rather than add padding to the input. + * + * For more details on calculating output shapes and padding for transposed convolutions (deconvolution here), see: + * https://arxiv.org/pdf/1603.07285v1.pdf + * + * @param {number[]} inputShape + */ + _calcOutputShape(inputShape) { + if (this.outputShape && this.outputPadding) { + return + } + + const inputRows = inputShape[0] + const inputCols = inputShape[1] + const [nbFilter, nbRow, nbCol] = this.kernelShape + + const outputRows = + this.padding === 'same' + ? inputRows * this.strides[0] + : inputRows * this.strides[0] + Math.max(nbRow - this.strides[0], 0) + const outputCols = + this.padding === 'same' + ? inputCols * this.strides[1] + : inputCols * this.strides[1] + Math.max(nbCol - this.strides[1], 0) + const outputChannels = nbFilter + + const paddingRow = + this.padding === 'same' ? Math.max(0, Math.floor((inputRows - 1) * this.strides[0] + nbRow - outputRows)) : 0 + const paddingCol = + this.padding === 'same' ? Math.max(0, Math.floor((inputCols - 1) * this.strides[1] + nbCol - outputCols)) : 0 + const paddingRowBefore = Math.floor(paddingRow / 2) + const paddingRowAfter = paddingRow - paddingRowBefore + const paddingColBefore = Math.floor(paddingCol / 2) + const paddingColAfter = paddingCol - paddingColBefore + + this.outputShape = [outputRows, outputCols, outputChannels] + this.outputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] + } + + /** + * Convert input image to column matrix, along channels axis + * + * shape: [inputRows, inputCols, inputChannels] -> [inputRows * inputCols, inputChannels] + * + * @param {Tensor} x + * @returns {Tensor} + */ + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape + + if (!this.imColsMat) { + this.imColsMat = new Tensor([], [inputRows * inputCols, inputChannels]) + } + + const channelRaveled = new Tensor([], [inputRows * inputCols]) + const channel = new Tensor([], [inputRows, inputCols]) + for (let c = 0; c < inputChannels; c++) { + ops.assign(channel.tensor, x.tensor.pick(null, null, c)) + channelRaveled.replaceTensorData(channel.tensor.data) + ops.assign(this.imColsMat.tensor.pick(null, c), channelRaveled.tensor) + } + + return this.imColsMat + } + + /** + * Convert filter weights to row matrix, along channels axis + * + * shape: [nbRow, nbCol, nbFilter, inputChannels] -> [inputChannels, nbRow * nbCol * nbFilter] + * + * @returns {Tensor} + */ + _w2row() { + const [nbRow, nbCol, nbFilter, inputChannels] = this.weights['kernel'].tensor.shape + + this.wRowsMat = new Tensor([], [inputChannels, nbRow * nbCol * nbFilter]) + + const channelRaveled = new Tensor([], [nbRow * nbCol * nbFilter]) + const channel = new Tensor([], [nbRow, nbCol, nbFilter]) + for (let c = 0; c < inputChannels; c++) { + ops.assign(channel.tensor, this.weights['kernel'].tensor.pick(null, null, null, c)) + channelRaveled.replaceTensorData(channel.tensor.data) + ops.assign(this.wRowsMat.tensor.pick(c, null), channelRaveled.tensor) + } + + return this.wRowsMat + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.inputShape = x.tensor.shape + this._calcOutputShape(this.inputShape) + this._im2col(x) + + const inputRows = x.tensor.shape[0] + const inputCols = x.tensor.shape[1] + const [nbFilter, nbRow, nbCol] = this.kernelShape + const matMul = new Tensor([], [inputRows * inputCols, nbRow * nbCol * nbFilter]) + + gemm(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1) + + // add padding which we will take away later + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.outputPadding + this.output = new Tensor([], this.outputShape) + let outputPadded = new Tensor( + [], + [ + this.outputShape[0] + paddingRowBefore + paddingRowAfter, + this.outputShape[1] + paddingColBefore + paddingColAfter, + this.outputShape[2] + ] + ) + + const patchShape = [nbRow, nbCol, nbFilter] + let patch = new Tensor([], patchShape) + let patchRaveled = new Tensor([], [nbRow * nbCol * nbFilter]) + let index = 0 + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + ops.assign(patchRaveled.tensor, matMul.tensor.pick(index, null)) + patch.replaceTensorData(patchRaveled.tensor.data) + const iOutPos = i * this.strides[0] + const jOutPos = j * this.strides[1] + ops.addeq( + outputPadded.tensor.hi(iOutPos + nbRow, jOutPos + nbCol, this.outputShape[2]).lo(iOutPos, jOutPos, 0), + patch.tensor + ) + index += 1 + } + } + + // remove padding + ops.assign( + this.output.tensor, + outputPadded.tensor + .hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, this.outputShape[2]) + .lo(paddingRowBefore, paddingColBefore, 0) + ) + + // bias + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + ops.addseq(this.output.tensor.pick(null, null, n), this.weights['bias'].tensor.get(n)) + } + } + + this.activationFunc(this.output) + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + + /** + * In GPU mode, we work directly on 2D-reshaped representations of the tensors. After the matrix multiply step produce + * matrix Y, the final output Z at coordinate [i,j] will be the summation of a number of elements of the matrix Y. + * Here, we calculate the indices of matrix Y for each coordinate [i,j] of Z, and encode these index maps as texture + * arrays. + */ + _createIndexMap() { + if (this.indexMap) { + return + } + + const inputRows = this.inputShape[0] + const inputCols = this.inputShape[1] + const [nbFilter, nbRow, nbCol] = this.kernelShape + + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.outputPadding + + const effectiveKernelSize = (nbRow - this.strides[0] + 1) * (nbCol - this.strides[1] + 1) + const indicesMapShape = [this.outputShape[0], this.outputShape[1], effectiveKernelSize] + const indicesMapShapePadded = [ + this.outputShape[0] + paddingRowBefore + paddingRowAfter, + this.outputShape[1] + paddingColBefore + paddingColAfter, + effectiveKernelSize + ] + const outputRowIndicesMap = new Tensor([], indicesMapShape, { type: Int32Array }) + const outputColIndicesMap = new Tensor([], indicesMapShape, { type: Int32Array }) + const outputRowIndicesMapPadded = new Tensor([], indicesMapShapePadded, { type: Int32Array }) + const outputColIndicesMapPadded = new Tensor([], indicesMapShapePadded, { type: Int32Array }) + ops.assigns(outputRowIndicesMap.tensor, -1) + ops.assigns(outputColIndicesMap.tensor, -1) + ops.assigns(outputRowIndicesMapPadded.tensor, -1) + ops.assigns(outputColIndicesMapPadded.tensor, -1) + + const matMulColIndicesPatch = new Tensor([], [nbRow, nbCol, nbFilter], { type: Int32Array }) + for (let i = 0; i < nbRow * nbCol * nbFilter; i++) { + matMulColIndicesPatch.tensor.data[i] = i + } + + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + const matMulRowIndex = i * inputCols + j + const iOutPos = i * this.strides[0] + const jOutPos = j * this.strides[1] + assignToRowIndicesMap( + outputRowIndicesMapPadded.tensor + .hi(iOutPos + nbRow, jOutPos + nbCol, effectiveKernelSize) + .lo(iOutPos, jOutPos, 0), + matMulRowIndex, + effectiveKernelSize + ) + assignToColIndicesMap( + outputColIndicesMapPadded.tensor + .hi(iOutPos + nbRow, jOutPos + nbCol, effectiveKernelSize) + .lo(iOutPos, jOutPos, 0), + matMulColIndicesPatch.tensor.pick(null, null, 0), + effectiveKernelSize + ) + } + } + + // remove padding + ops.assign( + outputRowIndicesMap.tensor, + outputRowIndicesMapPadded.tensor + .hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, effectiveKernelSize) + .lo(paddingRowBefore, paddingColBefore, 0) + ) + ops.assign( + outputColIndicesMap.tensor, + outputColIndicesMapPadded.tensor + .hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, effectiveKernelSize) + .lo(paddingRowBefore, paddingColBefore, 0) + ) + + // combine first two dimensions + const tiledIndicesMapShape = [this.outputShape[0] * this.outputShape[1], effectiveKernelSize] + this.indexMap = new Tensor([], tiledIndicesMapShape, { type: Int32Array }) + const channelData = new Tensor([], [effectiveKernelSize], { type: Int32Array }) + for (let i = 0; i < this.outputShape[0]; i++) { + for (let j = 0; j < this.outputShape[1]; j++) { + for (let k = 0; k < effectiveKernelSize; k++) { + // i * cols + j + const rowIndex = outputRowIndicesMap.tensor.get(i, j, k) + const colIndex = outputColIndicesMap.tensor.get(i, j, k) + if (rowIndex !== -1 && colIndex !== -1) { + channelData.tensor.set(k, rowIndex * this.weights['kernel'].glTextureShape[1] + colIndex) + } else { + channelData.tensor.set(k, -1) + } + } + ops.assign(this.indexMap.tensor.pick(i * this.outputShape[1] + j, null), channelData.tensor) + } + } + + this.indexMap.createGLTexture({ type: '2d', format: 'int', supportsTextureFragments: true }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + this._calcOutputShape(this.inputShape) + } else { + this.inputShape = x.tensor.shape + this._calcOutputShape(this.inputShape) + this._im2col(x) + this.imColsMat.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.imColsMat + + // create output textures if doesn't already exist + if (!this.matMulResult) { + const outputTextureShape = [input.glTextureShape[0], this.weights['kernel'].glTextureShape[1]] + this.matMulResult = new Tensor([], outputTextureShape) + this.matMulResult.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + if (this.activation !== 'linear' && !this.outputPreactiv) { + const outputTextureShape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]] + this.outputPreactiv = new Tensor([], outputTextureShape) + this.outputPreactiv.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.outputPreactiv.is2DReshaped = true + this.outputPreactiv.originalShape = this.outputShape + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + if (!this.output) { + const outputTextureShape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]] + this.output = new Tensor([], outputTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.output.is2DReshaped = true + this.output.originalShape = this.outputShape + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + + // Matrix Multiply with kernel + webgl2.runProgram({ + program: this.matMulProgram, + output: this.matMulResult, + inputs: [{ input: input, name: 'A' }, { input: this.weights['kernel'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }], + supportsTextureFragments: true + }) + + // Tranposed Convolution + this._createIndexMap() + const hasFragments = Boolean(this.matMulResult.glTextureFragments) + if (hasFragments) { + this.matMulResult.convert2DRowFragmentedGLTextureToColStack() + } + if (!this.convTransposeProgram) { + const convTransposeProgramSource = createGLSLProgram( + 'conv2dTranspose', + this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, + this.matMulResult.glTextureFragmentShape + ? this.matMulResult.glTextureFragmentShape + : this.matMulResult.glTextureShape, + this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, + this.useBias, + hasFragments + ) + this.convTransposeProgram = webgl2.compileProgram(convTransposeProgramSource) + } + webgl2.runProgram({ + program: this.convTransposeProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [ + { input: this.matMulResult, name: 'matMulResult' }, + { input: this.indexMap, name: 'indexMap' }, + ...(this.useBias ? [{ input: this.weights['bias'], name: 'bias' }] : []) + ], + supportsTextureFragments: true + }) + if (hasFragments) { + this.matMulResult.removeGLTextureFragmentsAsColStack() + } + + // Activation + if (this.activation !== 'linear') { + webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ input: this.outputPreactiv, name: 'x' }], + supportsTextureFragments: true + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2D() + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + } +} diff --git a/keras-js/src/layers/convolutional/Conv3D.js b/keras-js/src/layers/convolutional/Conv3D.js new file mode 100644 index 0000000000..aaee0ac210 --- /dev/null +++ b/keras-js/src/layers/convolutional/Conv3D.js @@ -0,0 +1,545 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import * as activations from '../../activations' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import * as tensorUtils from '../../utils/tensorUtils' +import ops from 'ndarray-ops' +import gemm from 'ndarray-gemm' +import mapInputProgramSource from '../../webgl/mapInput.glsl' +import mapInputFragmentsProgramSource from '../../webgl/mapInput.fragments.glsl' +import matMulProgramSource from '../../webgl/matMul.glsl' +import * as activationProgramSources from '../../activations/programSources' + +/** + * Conv3D layer class + */ +export default class Conv3D extends Layer { + /** + * Creates a Conv3D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.filters] - Number of convolution filters to use + * @param {number|number[]} [attrs.kernel_size] - Size of the convolution kernel + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Conv3D' + + const { + filters = 1, + kernel_size = [1, 1, 1], + strides = [1, 1, 1], + padding = 'valid', + data_format = 'channels_last', + dilation_rate = [1, 1, 1], + activation = 'linear', + use_bias = true + } = attrs + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size] + } else { + this.kernelShape = [filters, kernel_size, kernel_size, kernel_size] + } + + if (Array.isArray(strides)) { + this.strides = strides + } else { + this.strides = [strides, strides, strides] + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding + } else { + this.throwError('Invalid padding.') + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.') + } + + if (Array.isArray(dilation_rate)) { + this.dilationRate = dilation_rate + } else { + this.dilationRate = [dilation_rate, dilation_rate, dilation_rate] + } + if ( + (this.dilationRate[0] !== 1 || this.dilationRate[1] !== 1 || this.dilationRate[2] !== 1) && + (this.strides[0] !== 1 || this.strides[1] !== 1 || this.strides[2] !== 1) + ) { + // Currently, specifying any dilation_rate value != 1 is incompatible with specifying any stride value != 1 + // https://keras.io/layers/convolutional/#conv3d + this.throwError('Incompatible combination of dilation_rate with strides.') + } + + this.activation = activation + this.activationFunc = activations[activation] + + this.useBias = use_bias + + // Layer weights specification + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel'] + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + this.mapInputFragmentsProgram = webgl2.compileProgram(mapInputFragmentsProgramSource) + this.matMulProgram = webgl2.compileProgram(matMulProgramSource) + this.activationProgram = webgl2.compileProgram(activationProgramSources[this.activation]) + } + } + + /** + * Method for setting layer weights. Extends `super` method. + * + * W weight tensor is converted to `channels_last` mode if in `channels_first` mode. + * + * In `channels_last` mode, W weight tensor has shape [kernelDim1, kernelDim2, kernelDim3, inputChannels, nbFilter] + * + * In `channels_first` mode, W weight tensor has shape [nbFilter, inputChannels, kernelDim1, kernelDim2, kernelDim3] + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 4, 1, 0) + } + super.setWeights(weightsArr, false) + + this._w2row() + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat + this.weights['kernel'].createGLTexture({ type: '2d', format: 'float' }) + if (this.useBias) { + this.weights['bias'].createGLTexture({ type: '2d', format: 'float' }) + } + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * Method for computing output dimensions and padding, based on input dimensions, kernel size, and padding mode. + * + * For tensorflow implementation of padding, see: + * https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/common_shape_fns.cc + * + * @param {number[]} inputShape + */ + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return + } + + const inputDim1 = inputShape[0] + const inputDim2 = inputShape[1] + const inputDim3 = inputShape[2] + const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape + + // effective shape after filter dilation + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1) + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1) + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1) + + const outputDim1 = + this.padding === 'same' + ? Math.floor((inputDim1 + this.strides[0] - 1) / this.strides[0]) + : Math.floor((inputDim1 - kernelDim1Dilated + this.strides[0]) / this.strides[0]) + const outputDim2 = + this.padding === 'same' + ? Math.floor((inputDim2 + this.strides[1] - 1) / this.strides[1]) + : Math.floor((inputDim2 - kernelDim2Dilated + this.strides[1]) / this.strides[1]) + const outputDim3 = + this.padding === 'same' + ? Math.floor((inputDim3 + this.strides[2] - 1) / this.strides[2]) + : Math.floor((inputDim3 - kernelDim3Dilated + this.strides[2]) / this.strides[2]) + const outputChannels = nbFilter + + const paddingDim1 = + this.padding === 'same' + ? Math.max(0, Math.floor((outputDim1 - 1) * this.strides[0] + kernelDim1Dilated - inputDim1)) + : 0 + const paddingDim2 = + this.padding === 'same' + ? Math.max(0, Math.floor((outputDim2 - 1) * this.strides[1] + kernelDim2Dilated - inputDim2)) + : 0 + const paddingDim3 = + this.padding === 'same' + ? Math.max(0, Math.floor((outputDim3 - 1) * this.strides[2] + kernelDim3Dilated - inputDim3)) + : 0 + const paddingDim1Before = Math.floor(paddingDim1 / 2) + const paddingDim1After = paddingDim1 - paddingDim1Before + const paddingDim2Before = Math.floor(paddingDim2 / 2) + const paddingDim2After = paddingDim2 - paddingDim2Before + const paddingDim3Before = Math.floor(paddingDim3 / 2) + const paddingDim3After = paddingDim3 - paddingDim3Before + + this.outputShape = [outputDim1, outputDim2, outputDim3, outputChannels] + this.inputPadding = [ + paddingDim1Before, + paddingDim1After, + paddingDim2Before, + paddingDim2After, + paddingDim3Before, + paddingDim3After + ] + } + + /** + * Pad input tensor if necessary, for padding='same' + * + * @param {Tensor} x + * @param {number} [padValue] + * @returns {Tensor} + */ + _padInput(x, padValue = 0) { + if (this.padding === 'same') { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape + const [ + paddingDim1Before, + paddingDim1After, + paddingDim2Before, + paddingDim2After, + paddingDim3Before, + paddingDim3After + ] = this.inputPadding + const newDim1 = inputDim1 + paddingDim1Before + paddingDim1After + const newDim2 = inputDim2 + paddingDim2Before + paddingDim2After + const newDim3 = inputDim3 + paddingDim3Before + paddingDim3After + const _x = new Tensor([], [newDim1, newDim2, newDim3, inputChannels]) + if (padValue !== 0) { + ops.assigns(_x.tensor, padValue) + } + ops.assign( + _x.tensor + .hi( + inputDim1 + paddingDim1Before, + inputDim2 + paddingDim2Before, + inputDim3 + paddingDim3Before, + inputChannels + ) + .lo(paddingDim1Before, paddingDim2Before, paddingDim3Before, 0), + x.tensor + ) + return _x + } + return x + } + + /** + * Convert input volume to column matrix + * + * @param {Tensor} x + * @returns {Tensor} + */ + _vol2col(x) { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape + const kernelDim1 = this.kernelShape[1] + const kernelDim2 = this.kernelShape[2] + const kernelDim3 = this.kernelShape[3] + const outputDim1 = this.outputShape[0] + const outputDim2 = this.outputShape[1] + const outputDim3 = this.outputShape[2] + const nbPatches = outputDim1 * outputDim2 * outputDim3 + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels + + // effective shape after filter dilation + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1) + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1) + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1) + + if (!this.volColsMat) { + this.volColsMat = new Tensor([], [nbPatches, patchLen]) + } + + if ( + kernelDim1Dilated === 1 && + kernelDim2Dilated === 1 && + kernelDim3Dilated === 1 && + this.strides[0] === 1 && + this.strides[1] === 1 && + this.strides[2] === 1 + ) { + this.volColsMat.replaceTensorData(x.tensor.data) + return this.volColsMat + } + + const patch = new Tensor([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]) + let offset = 0 + for (let i = 0, limit = inputDim1 - kernelDim1Dilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - kernelDim2Dilated; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - kernelDim3Dilated; k <= limit; k += this.strides[2]) { + ops.assign( + patch.tensor, + x.tensor + .hi(i + kernelDim1Dilated, j + kernelDim2Dilated, k + kernelDim3Dilated, inputChannels) + .lo(i, j, k, 0) + .step(this.dilationRate[0], this.dilationRate[1], this.dilationRate[2], 1) + ) + this.volColsMat.tensor.data.set(patch.tensor.data, offset) + offset += patchLen + } + } + } + + return this.volColsMat + } + + /** + * Convert filter weights to row matrix + * + * @returns {Tensor} + */ + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[3] + const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels + + this.wRowsMat = new Tensor([], [patchLen, nbFilter]) + + const patch = new Tensor([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]) + const patchRaveled = new Tensor([], [patchLen]) + for (let n = 0; n < nbFilter; n++) { + ops.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, null, null, n)) + patchRaveled.replaceTensorData(patch.tensor.data) + ops.assign(this.wRowsMat.tensor.pick(null, n), patchRaveled.tensor) + } + + return this.wRowsMat + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.inputShape = x.tensor.shape + this._calcOutputShape(this.inputShape) + x = this._padInput(x) + this._vol2col(x) + + const nbFilter = this.kernelShape[0] + const outputDim1 = this.outputShape[0] + const outputDim2 = this.outputShape[1] + const outputDim3 = this.outputShape[2] + const nbPatches = outputDim1 * outputDim2 * outputDim3 + const matMul = new Tensor([], [nbPatches, nbFilter]) + + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + ops.assigns(matMul.tensor.pick(null, n), this.weights['bias'].tensor.get(n)) + } + } + gemm(matMul.tensor, this.volColsMat.tensor, this.wRowsMat.tensor, 1, 1) + + this.output = new Tensor([], this.outputShape) + + let outputChannelRaveled = new Tensor([], [outputDim1 * outputDim2 * outputDim3]) + let outputChannel = new Tensor([], [outputDim1, outputDim2, outputDim3]) + for (let n = 0; n < nbFilter; n++) { + ops.assign(outputChannelRaveled.tensor, matMul.tensor.pick(null, n)) + outputChannel.replaceTensorData(outputChannelRaveled.tensor.data) + ops.assign(this.output.tensor.pick(null, null, null, n), outputChannel.tensor) + } + + this.activationFunc(this.output) + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2) + } + } + + /** + * Creates a index mapping from the 2D-reshaped input tensor with associated 3D tensor shape to the representation + * required prior to the matrix multiply. This allows us to work directly on the 2D reshaped tensor representations + * rather than needing to reshape to the 3D reprentation and calling im2col. + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return + } + + let [inputDim1, inputDim2, inputDim3, inputChannels] = this.inputShape + + let indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + // padding for border mode 'same' + if (this.padding === 'same') { + const [ + paddingDim1Before, + paddingDim1After, + paddingDim2Before, + paddingDim2After, + paddingDim3Before, + paddingDim3After + ] = this.inputPadding + inputDim1 = inputDim1 + paddingDim1Before + paddingDim1After + inputDim2 = inputDim2 + paddingDim2Before + paddingDim2After + inputDim3 = inputDim3 + paddingDim3Before + paddingDim3After + const padValue = -1 + indices = this._padInput(indices, padValue) + } + + const kernelDim1 = this.kernelShape[1] + const kernelDim2 = this.kernelShape[2] + const kernelDim3 = this.kernelShape[3] + const outputDim1 = this.outputShape[0] + const outputDim2 = this.outputShape[1] + const outputDim3 = this.outputShape[2] + const nbPatches = outputDim1 * outputDim2 * outputDim3 + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels + + // effective shape after filter dilation + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1) + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1) + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1) + + this.indexMap = new Tensor([], [nbPatches, patchLen], { type: Int32Array }) + + const indicesPatch = new Tensor([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]) + let offset = 0 + for (let i = 0, limit = inputDim1 - kernelDim1Dilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - kernelDim2Dilated; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - kernelDim3Dilated; k <= limit; k += this.strides[2]) { + ops.assign( + indicesPatch.tensor, + indices.tensor + .hi(i + kernelDim1Dilated, j + kernelDim2Dilated, k + kernelDim3Dilated, inputChannels) + .lo(i, j, k, 0) + .step(this.dilationRate[0], this.dilationRate[1], this.dilationRate[2], 1) + ) + this.indexMap.tensor.data.set(indicesPatch.tensor.data, offset) + offset += patchLen + } + } + } + + this.indexMap.createGLTexture({ type: '2d', format: 'int', supportsTextureFragments: true }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + let outputTextureShape + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + this._calcOutputShape(this.inputShape) + this._createIndexMap(x.indicesForReshaped) + outputTextureShape = [this.indexMap.glTextureShape[0], this.weights['kernel'].glTextureShape[1]] + } else { + this.inputShape = x.tensor.shape + this._calcOutputShape(this.inputShape) + x = this._padInput(x) + this._vol2col(x) + this.volColsMat.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + outputTextureShape = [this.volColsMat.glTextureShape[0], this.weights['kernel'].glTextureShape[1]] + } + + // create output textures if doesn't already exist + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new Tensor([], outputTextureShape) + this.outputPreactiv.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.outputPreactiv.is2DReshaped = true + this.outputPreactiv.originalShape = this.outputShape + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + if (!this.output) { + this.output = new Tensor([], outputTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.output.is2DReshaped = true + this.output.originalShape = this.outputShape + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + + if (x.is2DReshaped || x.is2DSquareReshaped) { + // run conv2d program, which involves mapping the input using indexMap, and matrix multiply with weights + const hasFragments = Boolean(x.glTextureFragments) + if (hasFragments) { + x.convert2DRowFragmentedGLTextureToColStack() + } + if (!this.convProgram) { + const convProgramSource = createGLSLProgram( + 'conv2d', + this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, + x.glTextureFragmentShape ? x.glTextureFragmentShape : x.glTextureShape, + this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, + this.useBias, + hasFragments + ) + this.convProgram = webgl2.compileProgram(convProgramSource) + } + webgl2.runProgram({ + program: this.convProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [ + { input: x, name: 'x' }, + { input: this.indexMap, name: 'indexMap' }, + { input: this.weights['kernel'], name: 'kernel' }, + ...(this.useBias ? [{ input: this.weights['bias'], name: 'bias' }] : []) + ], + supportsTextureFragments: true + }) + if (hasFragments) { + x.removeGLTextureFragmentsAsColStack() + } + } else { + // run matrix multiply on result of vol2col + const matMulInputs = [{ input: this.volColsMat, name: 'A' }, { input: this.weights['kernel'], name: 'B' }] + if (this.useBias) { + matMulInputs.push({ input: this.weights['bias'], name: 'C' }) + } + webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ value: this.useBias ? 1 : 0, type: 'bool', name: 'addC' }], + supportsTextureFragments: true + }) + } + + // Activation + if (this.activation !== 'linear') { + webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ input: this.outputPreactiv, name: 'x' }], + supportsTextureFragments: true + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2D() + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2) + } + } + } +} diff --git a/keras-js/src/layers/convolutional/Cropping1D.js b/keras-js/src/layers/convolutional/Cropping1D.js new file mode 100644 index 0000000000..3e619e8cfd --- /dev/null +++ b/keras-js/src/layers/convolutional/Cropping1D.js @@ -0,0 +1,125 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * Cropping1D layer class + */ +export default class Cropping1D extends Layer { + /** + * Creates a Cropping1D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number|number[]} [attrs.cropping] - int or tuple of int (length 2) + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Cropping1D' + + const { cropping = [0, 0] } = attrs + + if (Array.isArray(cropping)) { + this.cropping = cropping + } else { + this.cropping = [cropping, cropping] + } + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.inputShape = x.tensor.shape + this.outputShape = [this.inputShape[0] - this.cropping[0] - this.cropping[1], this.inputShape[1]] + this.output = new Tensor([], this.outputShape) + ops.assign( + this.output.tensor, + x.tensor.hi(this.inputShape[0] - this.cropping[1], this.inputShape[2]).lo(this.cropping[0], 0) + ) + } + + /** + * Creates row/col index mappings to map input texture to output texture + */ + _createIndexMap() { + if (this.indexMap) { + return + } + + const indices = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesRow = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesCol = new Tensor([], this.inputShape, { type: Int32Array }) + for (let i = 0; i < this.inputShape[0]; i++) { + ops.assigns(indicesRow.tensor.pick(i, null), i) + } + for (let j = 0; j < this.inputShape[1]; j++) { + ops.assigns(indicesCol.tensor.pick(null, j), j) + } + // i * cols + j + ops.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]) + ops.addeq(indices.tensor, indicesCol.tensor) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + const sliceStart = [this.cropping[0], 0] + const sliceEnd = [this.inputShape[0] - this.cropping[1], this.inputShape[2]] + ops.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)) + + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + this.inputShape = x.tensor.shape + this.outputShape = [this.inputShape[0] - this.cropping[0] - this.cropping[1], this.inputShape[1]] + this._createIndexMap() + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/convolutional/Cropping2D.js b/keras-js/src/layers/convolutional/Cropping2D.js new file mode 100644 index 0000000000..9858a4aee2 --- /dev/null +++ b/keras-js/src/layers/convolutional/Cropping2D.js @@ -0,0 +1,166 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * Cropping2D layer class + */ +export default class Cropping2D extends Layer { + /** + * Creates a Cropping2D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number|number[]|number[][]} [attrs.cropping] - int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints + * @param {string} [attrs.data_format] - either 'channels_last' or 'channels_first' + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Cropping2D' + + const { cropping = [[0, 0], [0, 0]], data_format = 'channels_last' } = attrs + + if (Array.isArray(cropping)) { + if (Array.isArray(cropping[0])) { + // [[int, int], [int, int]] + this.cropping = cropping + } else { + // [int, int] + this.cropping = [[cropping[0], cropping[0]], [cropping[1], cropping[1]]] + } + } else { + // int + this.cropping = [[cropping, cropping], [cropping, cropping]] + } + + this.dataFormat = data_format + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0) + } + + this.inputShape = x.tensor.shape + this.outputShape = [ + this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], + this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], + this.inputShape[2] + ] + this.output = new Tensor([], this.outputShape) + ops.assign( + this.output.tensor, + x.tensor + .hi(this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2]) + .lo(this.cropping[0][0], this.cropping[1][0], 0) + ) + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1) + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + + /** + * Creates row/col index mappings to map input texture to output texture + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return + } + + const indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + + const sliceStart = + this.dataFormat === 'channels_first' + ? [0, this.cropping[0][0], this.cropping[1][0]] + : [this.cropping[0][0], this.cropping[1][0], 0] + const sliceEnd = + this.dataFormat === 'channels_first' + ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][1]] + : [this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2]] + + ops.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)) + + this.indexMap.reshapeTo2DSquare() + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare() + x.createGLTexture({ type: '2d', format: 'float' }) + } + this.inputShape = x.originalShape + this.outputShape = + this.dataFormat === 'channels_first' + ? [ + this.inputShape[0], + this.inputShape[1] - this.cropping[0][0] - this.cropping[0][1], + this.inputShape[2] - this.cropping[1][0] - this.cropping[1][1] + ] + : [ + this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], + this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], + this.inputShape[2] + ] + + this._createIndexMap(x.indicesForReshaped) + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.reshapeTo2DSquare() + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2DSquare() + } + } +} diff --git a/keras-js/src/layers/convolutional/Cropping3D.js b/keras-js/src/layers/convolutional/Cropping3D.js new file mode 100644 index 0000000000..f99f6f0087 --- /dev/null +++ b/keras-js/src/layers/convolutional/Cropping3D.js @@ -0,0 +1,184 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * Cropping3D layer class + */ +export default class Cropping3D extends Layer { + /** + * Creates a Cropping3D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number|number[]|number[][]} [attrs.cropping] - int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints + * @param {string} [attrs.data_format] - either 'channels_last' or 'channels_first' + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Cropping3D' + + const { cropping = [[0, 0], [0, 0], [0, 0]], data_format = 'channels_last' } = attrs + + if (Array.isArray(cropping)) { + if (Array.isArray(cropping[0])) { + // [[int, int], [int, int], [int, int]] + this.cropping = cropping + } else { + // [int, int, int] + this.cropping = [[cropping[0], cropping[0]], [cropping[1], cropping[1]], [cropping[2], cropping[2]]] + } + } else { + // int + this.cropping = [[cropping, cropping], [cropping, cropping], [cropping, cropping]] + } + + this.dataFormat = data_format + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0) + } + + this.inputShape = x.tensor.shape + this.outputShape = [ + this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], + this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], + this.inputShape[2] - this.cropping[2][0] - this.cropping[2][1], + this.inputShape[3] + ] + this.output = new Tensor([], this.outputShape) + ops.assign( + this.output.tensor, + x.tensor + .hi( + this.inputShape[0] - this.cropping[0][1], + this.inputShape[1] - this.cropping[1][1], + this.inputShape[2] - this.cropping[2][1], + this.inputShape[3] + ) + .lo(this.cropping[0][0], this.cropping[1][0], this.cropping[2][0], 0) + ) + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2) + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2) + } + } + + /** + * Creates row/col index mappings to map input texture to output texture + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return + } + + const indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + + const sliceStart = + this.dataFormat === 'channels_first' + ? [0, this.cropping[0][0], this.cropping[1][0], this.cropping[2][0]] + : [this.cropping[0][0], this.cropping[1][0], this.cropping[2][0], 0] + const sliceEnd = + this.dataFormat === 'channels_first' + ? [ + this.inputShape[0], + this.inputShape[1] - this.cropping[0][1], + this.inputShape[2] - this.cropping[1][1], + this.inputShape[3] - this.cropping[2][1] + ] + : [ + this.inputShape[0] - this.cropping[0][1], + this.inputShape[1] - this.cropping[1][1], + this.inputShape[2] - this.cropping[2][1], + this.inputShape[3] + ] + + ops.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)) + + this.indexMap.reshapeTo2DSquare() + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare() + x.createGLTexture({ type: '2d', format: 'float' }) + } + this.inputShape = x.originalShape + this.outputShape = + this.dataFormat === 'channels_first' + ? [ + this.inputShape[0], + this.inputShape[1] - this.cropping[0][0] - this.cropping[0][1], + this.inputShape[2] - this.cropping[1][0] - this.cropping[1][1], + this.inputShape[3] - this.cropping[2][0] - this.cropping[2][1] + ] + : [ + this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], + this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], + this.inputShape[2] - this.cropping[2][0] - this.cropping[2][1], + this.inputShape[3] + ] + + this._createIndexMap(x.indicesForReshaped) + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.reshapeTo2DSquare() + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2DSquare() + } + } +} diff --git a/keras-js/src/layers/convolutional/SeparableConv2D.js b/keras-js/src/layers/convolutional/SeparableConv2D.js new file mode 100644 index 0000000000..8d17fe1e5d --- /dev/null +++ b/keras-js/src/layers/convolutional/SeparableConv2D.js @@ -0,0 +1,360 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import * as activations from '../../activations' +import { webgl2 } from '../../WebGL2' +import * as tensorUtils from '../../utils/tensorUtils' +import ops from 'ndarray-ops' +import gemm from 'ndarray-gemm' +import Conv2D from './Conv2D' +import * as activationProgramSources from '../../activations/programSources' + +/** + * _DepthwiseConv2D layer class + */ +class _DepthwiseConv2D extends Conv2D { + /** + * @param {Object} [attrs] + */ + constructor(attrs = {}) { + super(attrs) + } + + /** + * @param {number[]} inputShape + */ + _calcOutputShape(inputShape) { + super._calcOutputShape(inputShape) + const nbFilter = this.kernelShape[0] + const inputChannels = inputShape[2] + this.outputShape[2] = nbFilter * inputChannels + } + + /** + * @param {Tensor} x + * @returns {Tensor} + */ + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape + const nbRow = this.kernelShape[1] + const nbCol = this.kernelShape[2] + const outputRows = this.outputShape[0] + const outputCols = this.outputShape[1] + const nbPatches = outputRows * outputCols + const patchLen = nbRow * nbCol + + if (!this.imColsMat) { + this.imColsMat = new Tensor([], [nbPatches * inputChannels, patchLen]) + } + + let patch = new Tensor([], [nbRow, nbCol, 1]) + let offset = 0 + for (let c = 0; c < inputChannels; c++) { + for (let i = 0, limit = inputRows - nbRow; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbCol; j <= limit; j += this.strides[1]) { + ops.assign(patch.tensor, x.tensor.hi(i + nbRow, j + nbCol, c + 1).lo(i, j, c)) + this.imColsMat.tensor.data.set(patch.tensor.data, offset) + offset += patchLen + } + } + } + + return this.imColsMat + } + + /** + * @returns {Tensor} + */ + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[2] + const [nbFilter, nbRow, nbCol] = this.kernelShape + const patchLen = nbRow * nbCol + + this.wRowsMat = new Tensor([], [patchLen, nbFilter * inputChannels]) + + let patch = new Tensor([], [nbRow, nbCol]) + let patchRaveled = new Tensor([], [patchLen]) + let p = 0 + for (let c = 0; c < inputChannels; c++) { + for (let n = 0; n < nbFilter; n++) { + ops.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, c, n)) + patchRaveled.replaceTensorData(patch.tensor.data) + ops.assign(this.wRowsMat.tensor.pick(null, p), patchRaveled.tensor) + p += 1 + } + } + + return this.wRowsMat + } + + /** + * @param {Tensor} x + */ + _callCPU(x) { + this.inputShape = x.tensor.shape + this._calcOutputShape(this.inputShape) + x = this._padInput(x) + this._im2col(x) + + const nbFilter = this.kernelShape[0] + const outputRows = this.outputShape[0] + const outputCols = this.outputShape[1] + const nbPatches = outputRows * outputCols + const inputChannels = this.inputShape[2] + const matMul = new Tensor([], [nbPatches * inputChannels, nbFilter * inputChannels]) + + gemm(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1) + + this.output = new Tensor([], this.outputShape) + + const outputDataLength = outputRows * outputCols * nbFilter * inputChannels + let dataFiltered = new Float32Array(outputDataLength) + for (let c = 0; c < inputChannels; c++) { + for (let n = c * outputDataLength + c * nbFilter; n < (c + 1) * outputDataLength; n += nbFilter * inputChannels) { + for (let m = 0; m < nbFilter; m++) { + dataFiltered[n + m - c * outputDataLength] = matMul.tensor.data[n + m] + } + } + } + this.output.replaceTensorData(dataFiltered) + } + + _createOutputReshapeIndexMap() { + if (this.reshapeIndexMap) { + return + } + + const nbFilter = this.kernelShape[0] + const reshape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]] + const reshapeRowIndices = new Tensor([], reshape, { type: Int32Array }) + const reshapeColIndices = new Tensor([], reshape, { type: Int32Array }) + this.reshapeIndexMap = new Tensor([], reshape, { type: Int32Array }) + for (let j = 0; j < reshape[1]; j++) { + for (let i = 0; i < reshape[0]; i++) { + ops.assigns(reshapeRowIndices.tensor.pick(i, j), i + Math.floor(j / nbFilter) * reshape[0]) + } + } + for (let j = 0; j < reshape[1]; j++) { + ops.assigns(reshapeColIndices.tensor.pick(null, j), j) + } + // i * cols + j + ops.muls(this.reshapeIndexMap.tensor, reshapeRowIndices.tensor, reshape[1]) + ops.addeq(this.reshapeIndexMap.tensor, reshapeColIndices.tensor) + + this.reshapeIndexMap.createGLTexture({ type: '2d', format: 'int', supportsTextureFragments: true }) + } + + /** + * @param {Tensor} x + */ + _callGPU(x) { + super._callGPU(x) + + this._createOutputReshapeIndexMap() + if (!this.outputReshaped) { + const reshape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]] + this.outputReshaped = new Tensor([], reshape) + this.outputReshaped.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.outputReshaped.is2DReshaped = true + this.outputReshaped.originalShape = this.outputShape + this.outputReshaped.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + if (this.output.glTextureFragments) { + this.output.convert2DRowFragmentedGLTextureToColStack() + } + webgl2.runProgram({ + program: this.output.glTextureFragments ? this.mapInputFragmentsProgram : this.mapInputProgram, + output: this.outputReshaped, + inputs: [{ input: this.output, name: 'x' }, { input: this.reshapeIndexMap, name: 'indexMap' }], + uniforms: [{ value: this.output.glTextureShape[1], type: 'int', name: 'inputCols' }], + supportsTextureFragments: true + }) + if (this.output.glTextureFragments) { + this.output.removeGLTextureFragmentsAsColStack() + } + } +} + +/** + * SeparableConv2D layer class + */ +export default class SeparableConv2D extends Layer { + /** + * Creates a SeparableConv2D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.filters] - Number of convolution filters to use + * @param {number|number[]} [attrs.kernel_size] - Size of the convolution kernel + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'SeparableConv2D' + + const { + filters = 1, + kernel_size = [1, 1], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + depth_multiplier = 1, + activation = 'linear', + use_bias = true + } = attrs + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size] + } else { + this.kernelShape = [filters, kernel_size, kernel_size] + } + + if (Array.isArray(strides)) { + this.strides = strides + } else { + this.strides = [strides, strides] + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding + } else { + this.throwError('Invalid padding.') + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.') + } + + this.activation = activation + this.activationFunc = activations[activation] + + if (padding === 'valid' || padding === 'same') { + this.padding = padding + } else { + this.throwError('Invalid padding.') + } + + this.useBias = use_bias + + // Layer weights specification + this.params = this.useBias + ? ['depthwise_kernel', 'pointwise_kernel', 'bias'] + : ['depthwise_kernel', 'pointwise_kernel'] + + // SeparableConv2D has two components: depthwise, and pointwise. + // Activation function and bias is applied at the end. + // Subsampling (striding) only performed on depthwise part, not the pointwise part. + this.depthwiseConvAttrs = { + filters: depth_multiplier, + kernel_size: [this.kernelShape[1], this.kernelShape[2]], + strides: this.strides, + padding, + data_format, + activation: 'linear', + use_bias: false, + gpu: attrs.gpu + } + this.pointwiseConvAttrs = { + filters, + kernel_size: [1, 1], + strides: [1, 1], + padding, + data_format, + activation: 'linear', + use_bias, + gpu: attrs.gpu + } + + // GPU setup + if (this.gpu) { + this.activationProgram = webgl2.compileProgram(activationProgramSources[this.activation]) + } + } + + /** + * Method for setting layer weights. Override `super` method since weights must be set in component Conv2D layers. + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + this._depthwiseConv = new _DepthwiseConv2D(this.depthwiseConvAttrs) + this._depthwiseConv.setWeights(weightsArr.slice(0, 1)) + this._pointwiseConv = new Conv2D(this.pointwiseConvAttrs) + this._pointwiseConv.setWeights(weightsArr.slice(1, 3)) + } + + /** + * Method for layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this._depthwiseConv._callCPU(x) + this._pointwiseConv._callCPU(this._depthwiseConv.output) + this.output = this._pointwiseConv.output + this.activationFunc(this.output) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + // prevent GPU -> CPU data transfer by specifying non-empty outbound nodes array on these internal Conv2D layers + this._depthwiseConv.outbound = [null] + this._pointwiseConv.outbound = [null] + + this._depthwiseConv._callGPU(x) + this._pointwiseConv._callGPU(this._depthwiseConv.outputReshaped) + + // Activation + if (this.activation === 'linear') { + this.output = this._pointwiseConv.output + } else { + if (!this.output) { + this.output = new Tensor([], this._pointwiseConv.output.glTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.output.is2DReshaped = true + this.output.originalShape = this._pointwiseConv.output.originalShape + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped( + this._pointwiseConv.output.originalShape, + false, + -1 + ) + } + this.outputPreactiv = this._pointwiseConv.output + webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ input: this.outputPreactiv, name: 'x' }], + supportsTextureFragments: true + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2D() + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + } +} diff --git a/keras-js/src/layers/convolutional/UpSampling1D.js b/keras-js/src/layers/convolutional/UpSampling1D.js new file mode 100644 index 0000000000..dc23944ba7 --- /dev/null +++ b/keras-js/src/layers/convolutional/UpSampling1D.js @@ -0,0 +1,119 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * UpSampling1D layer class + */ +export default class UpSampling1D extends Layer { + /** + * Creates a UpSampling1D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.size] - upsampling factor + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'UpSampling1D' + + const { size = 2 } = attrs + this.size = size + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.inputShape = x.tensor.shape + this.outputShape = [this.inputShape[0] * this.size, this.inputShape[1]] + this.output = new Tensor([], this.outputShape) + for (let i = 0; i < this.size; i++) { + ops.assign(this.output.tensor.lo(i, 0).step(this.size, 1), x.tensor) + } + } + + /** + * Creates row/col index mappings to map input texture to output texture + */ + _createIndexMap() { + if (this.indexMap) { + return + } + + const indices = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesRow = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesCol = new Tensor([], this.inputShape, { type: Int32Array }) + for (let i = 0; i < this.inputShape[0]; i++) { + ops.assigns(indicesRow.tensor.pick(i, null), i) + } + for (let j = 0; j < this.inputShape[1]; j++) { + ops.assigns(indicesCol.tensor.pick(null, j), j) + } + // i * cols + j + ops.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]) + ops.addeq(indices.tensor, indicesCol.tensor) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + for (let i = 0; i < this.size; i++) { + ops.assign(this.indexMap.tensor.lo(i, 0).step(this.size, 1), indices.tensor) + } + + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + this.inputShape = x.tensor.shape + this.outputShape = [this.inputShape[0] * this.size, this.inputShape[1]] + this._createIndexMap() + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/convolutional/UpSampling2D.js b/keras-js/src/layers/convolutional/UpSampling2D.js new file mode 100644 index 0000000000..8b6674e763 --- /dev/null +++ b/keras-js/src/layers/convolutional/UpSampling2D.js @@ -0,0 +1,144 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * UpSampling2D layer class + */ +export default class UpSampling2D extends Layer { + /** + * Creates a UpSampling2D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number|number[]} [attrs.size] - upsampling factor, int or tuple of int (length 2) + * @param {string} [attrs.data_format] - either 'channels_last' or 'channels_first' + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'UpSampling2D' + + const { size = [2, 2], data_format = 'channels_last' } = attrs + + if (Array.isArray(size)) { + this.size = size + } else { + this.size = [size, size] + } + + this.dataFormat = data_format + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0) + } + + this.inputShape = x.tensor.shape + this.outputShape = [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2]] + this.output = new Tensor([], this.outputShape) + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + ops.assign(this.output.tensor.lo(i, j, 0).step(this.size[0], this.size[1], 1), x.tensor) + } + } + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1) + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + + /** + * Creates row/col index mappings to map input texture to output texture + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return + } + + const indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + const sliceStart = this.dataFormat === 'channels_first' ? [0, i, j] : [i, j, 0] + const step = + this.dataFormat === 'channels_first' ? [1, this.size[0], this.size[1]] : [this.size[0], this.size[1], 1] + ops.assign(this.indexMap.tensor.lo(...sliceStart).step(...step), indices.tensor) + } + } + + this.indexMap.reshapeTo2DSquare() + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare() + x.createGLTexture({ type: '2d', format: 'float' }) + } + this.inputShape = x.originalShape + this.outputShape = + this.dataFormat === 'channels_first' + ? [this.inputShape[0], this.inputShape[1] * this.size[0], this.inputShape[2] * this.size[1]] + : [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2]] + + this._createIndexMap(x.indicesForReshaped) + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.reshapeTo2DSquare() + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2DSquare() + } + } +} diff --git a/keras-js/src/layers/convolutional/UpSampling3D.js b/keras-js/src/layers/convolutional/UpSampling3D.js new file mode 100644 index 0000000000..253ca78be2 --- /dev/null +++ b/keras-js/src/layers/convolutional/UpSampling3D.js @@ -0,0 +1,165 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * UpSampling3D layer class + */ +export default class UpSampling3D extends Layer { + /** + * Creates a UpSampling3D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number|number[]} [attrs.size] - upsampling factor, int or tuple of int (length 3) + * @param {string} [attrs.data_format] - either 'channels_last' or 'channels_first' + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'UpSampling3D' + + const { size = [2, 2, 2], data_format = 'channels_last' } = attrs + + if (Array.isArray(size)) { + this.size = size + } else { + this.size = [size, size, size] + } + + this.dataFormat = data_format + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0) + } + + this.inputShape = x.tensor.shape + this.outputShape = [ + this.inputShape[0] * this.size[0], + this.inputShape[1] * this.size[1], + this.inputShape[2] * this.size[2], + this.inputShape[3] + ] + this.output = new Tensor([], this.outputShape) + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + for (let k = 0; k < this.size[2]; k++) { + ops.assign(this.output.tensor.lo(i, j, k, 0).step(this.size[0], this.size[1], this.size[2], 1), x.tensor) + } + } + } + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2) + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2) + } + } + + /** + * Creates row/col index mappings to map input texture to output texture + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return + } + + const indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + for (let k = 0; k < this.size[2]; k++) { + const sliceStart = this.dataFormat === 'channels_first' ? [0, i, j, k] : [i, j, k, 0] + const step = + this.dataFormat === 'channels_first' + ? [1, this.size[0], this.size[1], this.size[2]] + : [this.size[0], this.size[1], this.size[2], 1] + ops.assign(this.indexMap.tensor.lo(...sliceStart).step(...step), indices.tensor) + } + } + } + + this.indexMap.reshapeTo2DSquare() + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare() + x.createGLTexture({ type: '2d', format: 'float' }) + } + this.inputShape = x.originalShape + this.outputShape = + this.dataFormat === 'channels_first' + ? [ + this.inputShape[0], + this.inputShape[1] * this.size[0], + this.inputShape[2] * this.size[1], + this.inputShape[3] * this.size[2] + ] + : [ + this.inputShape[0] * this.size[0], + this.inputShape[1] * this.size[1], + this.inputShape[2] * this.size[2], + this.inputShape[3] + ] + + this._createIndexMap(x.indicesForReshaped) + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.reshapeTo2DSquare() + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2DSquare() + } + } +} diff --git a/keras-js/src/layers/convolutional/ZeroPadding1D.js b/keras-js/src/layers/convolutional/ZeroPadding1D.js new file mode 100644 index 0000000000..b105afaffd --- /dev/null +++ b/keras-js/src/layers/convolutional/ZeroPadding1D.js @@ -0,0 +1,126 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * ZeroPadding1D layer class + */ +export default class ZeroPadding1D extends Layer { + /** + * Creates a ZeroPadding1D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number|number[]} [attrs.padding] - int or tuple of int (length 2) + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'ZeroPadding1D' + + const { padding = [1, 1] } = attrs + + if (Array.isArray(padding)) { + this.padding = padding + } else { + this.padding = [padding, padding] + } + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.inputShape = x.tensor.shape + this.outputShape = [this.inputShape[0] + this.padding[0] + this.padding[1], this.inputShape[1]] + this.output = new Tensor([], this.outputShape) + ops.assign( + this.output.tensor.hi(this.inputShape[0] + this.padding[0], this.inputShape[1]).lo(this.padding[0], 0), + x.tensor + ) + } + + /** + * Creates row/col index mappings to map input texture to output texture + */ + _createIndexMap() { + if (this.indexMap) { + return + } + + const indices = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesRow = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesCol = new Tensor([], this.inputShape, { type: Int32Array }) + for (let i = 0; i < this.inputShape[0]; i++) { + ops.assigns(indicesRow.tensor.pick(i, null), i) + } + for (let j = 0; j < this.inputShape[1]; j++) { + ops.assigns(indicesCol.tensor.pick(null, j), j) + } + // i * cols + j + ops.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]) + ops.addeq(indices.tensor, indicesCol.tensor) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + const sliceStart = [this.padding[0], 0] + const sliceEnd = [this.inputShape[0] + this.padding[0], this.inputShape[1]] + ops.assigns(this.indexMap.tensor, -1) + ops.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor) + + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + this.inputShape = x.tensor.shape + this.outputShape = [this.inputShape[0] + this.padding[0] + this.padding[1], this.inputShape[1]] + this._createIndexMap() + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/convolutional/ZeroPadding2D.js b/keras-js/src/layers/convolutional/ZeroPadding2D.js new file mode 100644 index 0000000000..7df16750a0 --- /dev/null +++ b/keras-js/src/layers/convolutional/ZeroPadding2D.js @@ -0,0 +1,167 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * ZeroPadding2D layer class + */ +export default class ZeroPadding2D extends Layer { + /** + * Creates a ZeroPadding2D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number|number[]|number[][]} [attrs.padding] - int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints + * @param {string} [attrs.data_format] - either 'channels_last' or 'channels_first' + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'ZeroPadding2D' + + const { padding = [[1, 1], [1, 1]], data_format = 'channels_last' } = attrs + + if (Array.isArray(padding)) { + if (Array.isArray(padding[0])) { + // [[int, int], [int, int]] + this.padding = padding + } else { + // [int, int] + this.padding = [[padding[0], padding[0]], [padding[1], padding[1]]] + } + } else { + // int + this.padding = [[padding, padding], [padding, padding]] + } + + this.dataFormat = data_format + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0) + } + + this.inputShape = x.tensor.shape + this.outputShape = [ + this.inputShape[0] + this.padding[0][0] + this.padding[0][1], + this.inputShape[1] + this.padding[1][0] + this.padding[1][1], + this.inputShape[2] + ] + this.output = new Tensor([], this.outputShape) + ops.assign( + this.output.tensor + .hi(this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2]) + .lo(this.padding[0][0], this.padding[1][0], 0), + x.tensor + ) + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1) + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + + /** + * Creates row/col index mappings to map input texture to output texture + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return + } + + const indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + + const sliceStart = + this.dataFormat === 'channels_first' + ? [0, this.padding[0][0], this.padding[1][0]] + : [this.padding[0][0], this.padding[1][0], 0] + const sliceEnd = + this.dataFormat === 'channels_first' + ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0], this.inputShape[2] + this.padding[1][0]] + : [this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2]] + + ops.assigns(this.indexMap.tensor, -1) + ops.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor) + + this.indexMap.reshapeTo2DSquare() + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare() + x.createGLTexture({ type: '2d', format: 'float' }) + } + this.inputShape = x.originalShape + this.outputShape = + this.dataFormat === 'channels_first' + ? [ + this.inputShape[0], + this.inputShape[1] + this.padding[0][0] + this.padding[0][1], + this.inputShape[2] + this.padding[1][0] + this.padding[1][1] + ] + : [ + this.inputShape[0] + this.padding[0][0] + this.padding[0][1], + this.inputShape[1] + this.padding[1][0] + this.padding[1][1], + this.inputShape[2] + ] + + this._createIndexMap(x.indicesForReshaped) + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.reshapeTo2DSquare() + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2DSquare() + } + } +} diff --git a/keras-js/src/layers/convolutional/ZeroPadding3D.js b/keras-js/src/layers/convolutional/ZeroPadding3D.js new file mode 100644 index 0000000000..18800a4949 --- /dev/null +++ b/keras-js/src/layers/convolutional/ZeroPadding3D.js @@ -0,0 +1,185 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * ZeroPadding3D layer class + */ +export default class ZeroPadding3D extends Layer { + /** + * Creates a ZeroPadding3D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number|number[]|number[][]} [attrs.padding] - int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints + * @param {string} [attrs.data_format] - either 'channels_last' or 'channels_first' + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'ZeroPadding3D' + + const { padding = [[1, 1], [1, 1], [1, 1]], data_format = 'channels_last' } = attrs + + if (Array.isArray(padding)) { + if (Array.isArray(padding[0])) { + // [[int, int], [int, int], [int, int]] + this.padding = padding + } else { + // [int, int, int] + this.padding = [[padding[0], padding[0]], [padding[1], padding[1]], [padding[2], padding[2]]] + } + } else { + // int + this.padding = [[padding, padding], [padding, padding], [padding, padding]] + } + + this.dataFormat = data_format + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0) + } + + this.inputShape = x.tensor.shape + this.outputShape = [ + this.inputShape[0] + this.padding[0][0] + this.padding[0][1], + this.inputShape[1] + this.padding[1][0] + this.padding[1][1], + this.inputShape[2] + this.padding[2][0] + this.padding[2][1], + this.inputShape[3] + ] + this.output = new Tensor([], this.outputShape) + ops.assign( + this.output.tensor + .hi( + this.inputShape[0] + this.padding[0][0], + this.inputShape[1] + this.padding[1][0], + this.inputShape[2] + this.padding[2][0], + this.inputShape[3] + ) + .lo(this.padding[0][0], this.padding[1][0], this.padding[2][0], 0), + x.tensor + ) + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2) + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2) + } + } + + /** + * Creates row/col index mappings to map input texture to output texture + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return + } + + const indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + this.indexMap = new Tensor([], this.outputShape, { type: Int32Array }) + + const sliceStart = + this.dataFormat === 'channels_first' + ? [0, this.padding[0][0], this.padding[1][0], this.padding[2][0]] + : [this.padding[0][0], this.padding[1][0], this.padding[2][0], 0] + const sliceEnd = + this.dataFormat === 'channels_first' + ? [ + this.inputShape[0], + this.inputShape[1] + this.padding[0][0], + this.inputShape[2] + this.padding[1][0], + this.inputShape[3] + this.padding[2][0] + ] + : [ + this.inputShape[0] + this.padding[0][0], + this.inputShape[1] + this.padding[1][0], + this.inputShape[2] + this.padding[2][0], + this.inputShape[3] + ] + + ops.assigns(this.indexMap.tensor, -1) + ops.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor) + + this.indexMap.reshapeTo2DSquare() + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare() + x.createGLTexture({ type: '2d', format: 'float' }) + } + this.inputShape = x.originalShape + this.outputShape = + this.dataFormat === 'channels_first' + ? [ + this.inputShape[0], + this.inputShape[1] + this.padding[0][0] + this.padding[0][1], + this.inputShape[2] + this.padding[1][0] + this.padding[1][1], + this.inputShape[3] + this.padding[2][0] + this.padding[2][1] + ] + : [ + this.inputShape[0] + this.padding[0][0] + this.padding[0][1], + this.inputShape[1] + this.padding[1][0] + this.padding[1][1], + this.inputShape[2] + this.padding[2][0] + this.padding[2][1], + this.inputShape[3] + ] + + this._createIndexMap(x.indicesForReshaped) + + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.reshapeTo2DSquare() + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2DSquare() + } + } +} diff --git a/keras-js/src/layers/convolutional/index.js b/keras-js/src/layers/convolutional/index.js new file mode 100644 index 0000000000..ebca04cc9f --- /dev/null +++ b/keras-js/src/layers/convolutional/index.js @@ -0,0 +1,31 @@ +import Conv1D from './Conv1D' +import Conv2D from './Conv2D' +import SeparableConv2D from './SeparableConv2D' +import Conv2DTranspose from './Conv2DTranspose' +import Conv3D from './Conv3D' +import Cropping1D from './Cropping1D' +import Cropping2D from './Cropping2D' +import Cropping3D from './Cropping3D' +import UpSampling1D from './UpSampling1D' +import UpSampling2D from './UpSampling2D' +import UpSampling3D from './UpSampling3D' +import ZeroPadding1D from './ZeroPadding1D' +import ZeroPadding2D from './ZeroPadding2D' +import ZeroPadding3D from './ZeroPadding3D' + +export { + Conv1D, + Conv2D, + SeparableConv2D, + Conv2DTranspose, + Conv3D, + Cropping1D, + Cropping2D, + Cropping3D, + UpSampling1D, + UpSampling2D, + UpSampling3D, + ZeroPadding1D, + ZeroPadding2D, + ZeroPadding3D +} diff --git a/keras-js/src/layers/core/Activation.js b/keras-js/src/layers/core/Activation.js new file mode 100644 index 0000000000..8a54ba4e7a --- /dev/null +++ b/keras-js/src/layers/core/Activation.js @@ -0,0 +1,105 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import * as activations from '../../activations' +import * as activationProgramSources from '../../activations/programSources' + +/** + * Activation layer class + */ +export default class Activation extends Layer { + /** + * Creates an Activation layer + * + * @param {Object} [attrs] - layer config attributes + * @param {String} [attrs.activation] - name of activation function + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Activation' + + const { activation = 'linear' } = attrs + + this.activation = activation + this.activationFunc = activations[activation] + + // GPU setup + if (this.gpu) { + this.program = webgl2.compileProgram(activationProgramSources[this.activation]) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.activation === 'linear') { + this.output = x + return this.output + } + + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.output = new Tensor(new x.arrayType(x.tensor.data), x.tensor.shape) + this.activationFunc(this.output) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + + if (!this.output) { + this.output = new Tensor([], x.glTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + if (x.is1D) { + this.output.is1D = x.is1D + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped + } + this.output.originalShape = x.originalShape + this.output.indicesForReshaped = x.indicesForReshaped + } + } + + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ input: x, name: 'x' }], + supportsTextureFragments: true + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/core/Dense.js b/keras-js/src/layers/core/Dense.js new file mode 100644 index 0000000000..c2721a6739 --- /dev/null +++ b/keras-js/src/layers/core/Dense.js @@ -0,0 +1,122 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import * as activations from '../../activations' +import { webgl2 } from '../../WebGL2' +import { gemv } from 'ndarray-blas-level2' +import ops from 'ndarray-ops' +import matMulProgramSource from '../../webgl/matMul.glsl' +import * as activationProgramSources from '../../activations/programSources' + +/** + * Dense layer class + */ +export default class Dense extends Layer { + /** + * Creates a Dense layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.units] - output dimension size + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Dense' + + const { units = 1, activation = 'linear', input_dim = null, use_bias = true } = attrs + + this.activation = activation + this.activationFunc = activations[this.activation] + this.units = units + this.input_dim = input_dim + this.use_bias = use_bias + + // Layer weights specification + this.params = this.use_bias ? ['kernel', 'bias'] : ['kernel'] + + // Input shape specification + if (this.input_dim) { + this.inputShape = [this.input_dim] + } + + // GPU setup + if (this.gpu) { + this.matMulProgram = webgl2.compileProgram(matMulProgramSource) + this.activationProgram = webgl2.compileProgram(activationProgramSources[this.activation]) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.output = new Tensor([], [this.units]) + if (this.use_bias) { + ops.assign(this.output.tensor, this.weights['bias'].tensor) + } + gemv(1, this.weights['kernel'].tensor.transpose(1, 0), x.tensor, 1, this.output.tensor) + this.activationFunc(this.output) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + // create output textures if doesn't already exist + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new Tensor([], [this.units]) + this.outputPreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.output) { + this.output = new Tensor([], [this.units]) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + // Matrix Multiply + const matMulInputs = [{ input: x, name: 'A' }, { input: this.weights['kernel'], name: 'B' }] + if (this.use_bias) { + matMulInputs.push({ input: this.weights['bias'], name: 'C' }) + } + webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ value: this.use_bias ? 1 : 0, type: 'bool', name: 'addC' }] + }) + + // Activation + if (this.activation !== 'linear') { + webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ input: this.outputPreactiv, name: 'x' }] + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/core/Dropout.js b/keras-js/src/layers/core/Dropout.js new file mode 100644 index 0000000000..734036f556 --- /dev/null +++ b/keras-js/src/layers/core/Dropout.js @@ -0,0 +1,34 @@ +import Layer from '../../Layer' + +/** + * Dropout layer class + * Note that this layer is here only for compatibility purposes, + * as it's only active during training phase. + */ +export default class Dropout extends Layer { + /** + * Creates an Dropout layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.rate] - fraction of the input units to drop (between 0 and 1) + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Dropout' + + const { rate = 0.5 } = attrs + + this.rate = Math.min(Math.max(0, rate), 1) + } + + /** + * Method for layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + this.output = x + return this.output + } +} diff --git a/keras-js/src/layers/core/Flatten.fragments.glsl b/keras-js/src/layers/core/Flatten.fragments.glsl new file mode 100644 index 0000000000..7c45c4e202 --- /dev/null +++ b/keras-js/src/layers/core/Flatten.fragments.glsl @@ -0,0 +1,20 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform int outputSize; +uniform int inputRows; +uniform int inputCols; +out vec4 outColor; + +void main() { + int out_x = int(float(outputSize) * outTex.x); + int out_y = 0; + + int rowIndex = int(mod(floor(float(out_x) / float(inputCols)), float(inputRows))); + int colIndex = int(mod(float(out_x), float(inputCols))); + int fragmentIndex = int(floor(float(out_x) / (float(inputRows) * float(inputCols)))); + colIndex += fragmentIndex * inputCols; + outColor = vec4(texelFetch(x, ivec2(colIndex, rowIndex), 0).r); +} diff --git a/keras-js/src/layers/core/Flatten.glsl b/keras-js/src/layers/core/Flatten.glsl new file mode 100644 index 0000000000..9b7e729d8c --- /dev/null +++ b/keras-js/src/layers/core/Flatten.glsl @@ -0,0 +1,17 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform int outputSize; +uniform int inputCols; +out vec4 outColor; + +void main() { + int out_x = int(float(outputSize) * outTex.x); + int out_y = 0; + + int i = int(floor(float(out_x) / float(inputCols))); + int j = int(mod(float(out_x), float(inputCols))); + outColor = vec4(texelFetch(x, ivec2(j, i), 0).r); +} diff --git a/keras-js/src/layers/core/Flatten.js b/keras-js/src/layers/core/Flatten.js new file mode 100644 index 0000000000..fb63f4f8a7 --- /dev/null +++ b/keras-js/src/layers/core/Flatten.js @@ -0,0 +1,109 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import flattenProgramSource from './Flatten.glsl' +import flattenFragmentsProgramSource from './Flatten.fragments.glsl' + +/** + * Flatten layer class + * Turns tensor into 1-d. Note there is no concept of batch size in these layers (single-batch). + */ +export default class Flatten extends Layer { + /** + * Creates a Flatten layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Flatten' + + // GPU setup + if (this.gpu) { + this.flattenProgram = webgl2.compileProgram(flattenProgramSource) + this.flattenFragmentsProgram = webgl2.compileProgram(flattenFragmentsProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + if (x.tensor.shape.length <= 1) { + this.output = x + } else { + this.output = new Tensor([], [x.tensor.shape.reduce((a, b) => a * b, 1)]) + this.output.replaceTensorData(x.tensor.data) + } + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ type: '2d', format: 'float' }) + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D() + x.createGLTexture({ type: '2d', format: 'float' }) + } + } + + if (!this.output) { + this.output = new Tensor([], [x.glTextureShape.reduce((a, b) => a * b, 1)]) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + if (x.glTextureFragments) { + x.convert2DRowFragmentedGLTextureToColStack() + webgl2.runProgram({ + program: this.flattenFragmentsProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }], + uniforms: [ + { value: this.output.glTextureShape[1], type: 'int', name: 'outputSize' }, + { value: x.glTextureShape[0], type: 'int', name: 'inputRows' }, + { value: x.glTextureShape[1], type: 'int', name: 'inputCols' } + ], + supportsTextureFragments: true + }) + x.removeGLTextureFragmentsAsColStack() + } else { + webgl2.runProgram({ + program: this.flattenProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }], + uniforms: [ + { value: this.output.glTextureShape[1], type: 'int', name: 'outputSize' }, + { value: x.glTextureShape[1], type: 'int', name: 'inputCols' } + ], + supportsTextureFragments: true + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/core/Permute.js b/keras-js/src/layers/core/Permute.js new file mode 100644 index 0000000000..d79d428897 --- /dev/null +++ b/keras-js/src/layers/core/Permute.js @@ -0,0 +1,166 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import _ from 'lodash' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * Permute layer class + * Note there is no concept of batch size in these layers (single-batch), so dim numbers 1 less + * i.e., dim 1 in keras corresponds to dim 0 here, etc. + */ +export default class Permute extends Layer { + /** + * Creates a Permute layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number[]} [attrs.dims] + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Permute' + + const { dims = [] } = attrs + this.dims = dims.map(dim => dim - 1) + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (x.tensor.shape.length <= 1 || _.isEqual(_.range(x.tensor.shape.length), this.dims)) { + this.output = x + return this.output + } + + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + if (this.dims.length !== x.tensor.shape.length) { + this.throwError('The specified dims permutation must match the number of dimensions.') + } + + const outputShape = this.dims.map(i => x.tensor.shape[i]) + this.output = new Tensor([], outputShape) + ops.assign(this.output.tensor, x.tensor.transpose(...this.dims)) + } + + /** + * Creates row/col index mappings to map input texture to output texture + */ + _createIndexMap() { + if (this.indexMap) { + return + } + + const indices = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesRow = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesCol = new Tensor([], this.inputShape, { type: Int32Array }) + + if (this.inputShape.length === 2) { + for (let i = 0; i < this.inputShape[0]; i++) { + ops.assigns(indicesRow.tensor.pick(i, null), i) + } + } else if (this.inputShape.length === 3) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + ops.assigns(indicesRow.tensor.pick(i, j, null), i * this.inputShape[1] + j) + } + } + } else if (this.inputShape.length === 4) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + for (let k = 0; k < this.inputShape[2]; k++) { + ops.assigns( + indicesRow.tensor.pick(i, j, k, null), + i * this.inputShape[1] * this.inputShape[2] + j * this.inputShape[2] + k + ) + } + } + } + } + for (let c = 0; c < _.last(this.inputShape); c++) { + ops.assigns(indicesCol.tensor.pick(...Array(this.inputShape.length - 1).fill(null), c), c) + } + // i * cols + j + ops.muls(indices.tensor, indicesRow.tensor, _.last(this.inputShape)) + ops.addeq(indices.tensor, indicesCol.tensor) + + const outputShape = this.dims.map(i => this.inputShape[i]) + this.indexMap = new Tensor([], outputShape, { type: Int32Array }) + ops.assign(this.indexMap.tensor, indices.tensor.transpose(...this.dims)) + if (outputShape.length > 2) { + this.indexMap.reshapeTo2D() + } + + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + this.inputShape = x.tensor.shape + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ type: '2d', format: 'float' }) + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D() + x.createGLTexture({ type: '2d', format: 'float' }) + } + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + this.inputShape = x.tensor.shape + } + this._createIndexMap() + + if (!this.output) { + const outputShape = this.dims.map(i => this.inputShape[i]) + this.output = new Tensor([], outputShape) + if (outputShape.length > 2) { + this.output.reshapeTo2D() + } + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/core/RepeatVector.glsl b/keras-js/src/layers/core/RepeatVector.glsl new file mode 100644 index 0000000000..eb29ef9478 --- /dev/null +++ b/keras-js/src/layers/core/RepeatVector.glsl @@ -0,0 +1,10 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +out vec4 outColor; + +void main() { + outColor = texture(x, vec2(outTex.x, 0)); +} diff --git a/keras-js/src/layers/core/RepeatVector.js b/keras-js/src/layers/core/RepeatVector.js new file mode 100644 index 0000000000..d45dfb0f27 --- /dev/null +++ b/keras-js/src/layers/core/RepeatVector.js @@ -0,0 +1,87 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import unsqueeze from 'ndarray-unsqueeze' +import tile from 'ndarray-tile' +import programSource from './RepeatVector.glsl' + +/** + * RepeatVector layer class + * Turns 2D tensors of shape [features] to 3D tensors of shape [n, features]. + * Note there is no concept of batch size in these layers (single-batch) so we're actually going from 1D to 2D. + */ +export default class RepeatVector extends Layer { + /** + * Creates a RepeatVector layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.n] + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'RepeatVector' + + const { n = 1 } = attrs + this.n = n + + // GPU setup + if (this.gpu) { + this.program = webgl2.compileProgram(programSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + if (x.tensor.shape.length !== 1) { + this.throwError('Only 1D tensor inputs allowed.') + } + this.output = new Tensor([], [this.n, x.tensor.shape[1]]) + this.output.tensor = tile(unsqueeze(x.tensor, 0), [this.n, 1]) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.output) { + this.output = new Tensor([], [this.n, x.glTextureShape[1]]) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ input: x, name: 'x' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/core/Reshape.js b/keras-js/src/layers/core/Reshape.js new file mode 100644 index 0000000000..9fa2f84107 --- /dev/null +++ b/keras-js/src/layers/core/Reshape.js @@ -0,0 +1,156 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import _ from 'lodash' +import ops from 'ndarray-ops' +import mapInputProgramSource from '../../webgl/mapInput.glsl' + +/** + * Reshape layer class + * Note there is no concept of batch size in these layers (single-batch). + */ +export default class Reshape extends Layer { + /** + * Creates a Reshape layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number[]} [attrs.target_shape] + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Reshape' + + const { target_shape = [] } = attrs + this.targetShape = target_shape + + // GPU setup + if (this.gpu) { + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + if (this.targetShape.reduce((a, b) => a * b, 1) !== x.tensor.size) { + this.throwError('The total size of new array must be unchanged in reshape layer.') + } + this.output = new Tensor([], this.targetShape) + this.output.replaceTensorData(x.tensor.data) + } + + /** + * Creates row/col index mappings to map input texture to output texture + */ + _createIndexMap() { + if (this.indexMap) { + return + } + + const indices = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesRow = new Tensor([], this.inputShape, { type: Int32Array }) + const indicesCol = new Tensor([], this.inputShape, { type: Int32Array }) + + if (this.inputShape.length === 2) { + for (let i = 0; i < this.inputShape[0]; i++) { + ops.assigns(indicesRow.tensor.pick(i, null), i) + } + } else if (this.inputShape.length === 3) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + ops.assigns(indicesRow.tensor.pick(i, j, null), i * this.inputShape[1] + j) + } + } + } else if (this.inputShape.length === 4) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + for (let k = 0; k < this.inputShape[2]; k++) { + ops.assigns( + indicesRow.tensor.pick(i, j, k, null), + i * this.inputShape[1] * this.inputShape[2] + j * this.inputShape[2] + k + ) + } + } + } + } + for (let c = 0; c < _.last(this.inputShape); c++) { + ops.assigns(indicesCol.tensor.pick(...Array(this.inputShape.length - 1).fill(null), c), c) + } + // i * cols + j + ops.muls(indices.tensor, indicesRow.tensor, _.last(this.inputShape)) + ops.addeq(indices.tensor, indicesCol.tensor) + + this.indexMap = new Tensor([], this.targetShape, { type: Int32Array }) + this.indexMap.replaceTensorData(new Int32Array(indices.tensor.data)) + if (this.targetShape.length > 2) { + this.indexMap.reshapeTo2D() + } + + this.indexMap.createGLTexture({ type: '2d', format: 'int' }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + this.inputShape = x.tensor.shape + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ type: '2d', format: 'float' }) + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D() + x.createGLTexture({ type: '2d', format: 'float' }) + } + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + this.inputShape = x.tensor.shape + } + this._createIndexMap() + + if (!this.output) { + this.output = new Tensor([], this.targetShape) + if (this.targetShape.length > 2) { + this.output.reshapeTo2D() + } + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.indexMap, name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/core/SpatialDropout1D.js b/keras-js/src/layers/core/SpatialDropout1D.js new file mode 100644 index 0000000000..2f5b055a9c --- /dev/null +++ b/keras-js/src/layers/core/SpatialDropout1D.js @@ -0,0 +1,34 @@ +import Layer from '../../Layer' + +/** + * SpatialDropout1D layer class + * Note that this layer is here only for compatibility purposes, + * as it's only active during training phase. + */ +export default class SpatialDropout1D extends Layer { + /** + * Creates an SpatialDropout1D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.p] - fraction of the input units to drop (between 0 and 1) + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'SpatialDropout1D' + + const { p = 0.5 } = attrs + + this.p = Math.min(Math.max(0, p), 1) + } + + /** + * Method for layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + this.output = x + return this.output + } +} diff --git a/keras-js/src/layers/core/SpatialDropout2D.js b/keras-js/src/layers/core/SpatialDropout2D.js new file mode 100644 index 0000000000..6fb7984b3a --- /dev/null +++ b/keras-js/src/layers/core/SpatialDropout2D.js @@ -0,0 +1,36 @@ +import Layer from '../../Layer' + +/** + * SpatialDropout2D layer class + * Note that this layer is here only for compatibility purposes, + * as it's only active during training phase. + */ +export default class SpatialDropout2D extends Layer { + /** + * Creates an SpatialDropout2D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.rate] - fraction of the input units to drop (between 0 and 1) + * @param {string} [attrs.data_format] - channels_first` or `channels_last` + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'SpatialDropout2D' + + const { rate = 0.5, data_format = 'channels_last' } = attrs + + this.rate = Math.min(Math.max(0, rate), 1) + this.dataFormat = data_format + } + + /** + * Method for layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + this.output = x + return this.output + } +} diff --git a/keras-js/src/layers/core/SpatialDropout3D.js b/keras-js/src/layers/core/SpatialDropout3D.js new file mode 100644 index 0000000000..520b898326 --- /dev/null +++ b/keras-js/src/layers/core/SpatialDropout3D.js @@ -0,0 +1,36 @@ +import Layer from '../../Layer' + +/** + * SpatialDropout3D layer class + * Note that this layer is here only for compatibility purposes, + * as it's only active during training phase. + */ +export default class SpatialDropout3D extends Layer { + /** + * Creates an SpatialDropout3D layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.rate] - fraction of the input units to drop (between 0 and 1) + * @param {string} [attrs.data_format] - channels_first` or `channels_last` + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'SpatialDropout3D' + + const { rate = 0.5, data_format = 'channels_last' } = attrs + + this.rate = Math.min(Math.max(0, rate), 1) + this.dataFormat = data_format + } + + /** + * Method for layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + this.output = x + return this.output + } +} diff --git a/keras-js/src/layers/core/index.js b/keras-js/src/layers/core/index.js new file mode 100644 index 0000000000..b7af847e58 --- /dev/null +++ b/keras-js/src/layers/core/index.js @@ -0,0 +1,23 @@ +import Dense from './Dense' +import Activation from './Activation' +import Dropout from './Dropout' +import SpatialDropout1D from './SpatialDropout1D' +import SpatialDropout2D from './SpatialDropout2D' +import SpatialDropout3D from './SpatialDropout3D' +import Flatten from './Flatten' +import Reshape from './Reshape' +import Permute from './Permute' +import RepeatVector from './RepeatVector' + +export { + Dense, + Activation, + Dropout, + SpatialDropout1D, + SpatialDropout2D, + SpatialDropout3D, + Flatten, + Reshape, + Permute, + RepeatVector +} diff --git a/keras-js/src/layers/embeddings/Embedding.glsl b/keras-js/src/layers/embeddings/Embedding.glsl new file mode 100644 index 0000000000..129de5a550 --- /dev/null +++ b/keras-js/src/layers/embeddings/Embedding.glsl @@ -0,0 +1,17 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform sampler2D embeddings; +out vec4 outColor; + +void main() { + ivec2 x_size = textureSize(x, 0); + ivec2 embeddings_size = textureSize(embeddings, 0); + int out_x = int(float(embeddings_size[0]) * outTex.x); + int out_y = int(float(x_size[0]) * outTex.y); + + int index = int(texelFetch(x, ivec2(out_y, 0), 0).r); + outColor = texelFetch(embeddings, ivec2(out_x, index), 0); +} diff --git a/keras-js/src/layers/embeddings/Embedding.js b/keras-js/src/layers/embeddings/Embedding.js new file mode 100644 index 0000000000..8770d2eafe --- /dev/null +++ b/keras-js/src/layers/embeddings/Embedding.js @@ -0,0 +1,92 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import programSource from './Embedding.glsl' + +/** + * Embedding layer class + */ +export default class Embedding extends Layer { + /** + * Creates a Embedding layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Embedding' + + const { input_dim = 1, output_dim = 1, input_length = 0, mask_zero = false } = attrs + + this.inputDim = input_dim + this.outputDim = output_dim + this.inputLength = input_length + + // mask_zero will be important for subsequent layers + this.maskZero = mask_zero + + // Layer weights specification + this.params = ['embeddings'] + + // GPU setup + if (this.gpu) { + this.program = webgl2.compileProgram(programSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.output = new Tensor([], [x.tensor.shape[0], this.weights['embeddings'].tensor.shape[1]]) + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + ops.assign(this.output.tensor.pick(i, null), this.weights['embeddings'].tensor.pick(x.tensor.get(i), null)) + } + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.output) { + this.output = new Tensor([], [x.glTextureShape[1], this.weights['embeddings'].glTextureShape[1]]) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.weights['embeddings'], name: 'embeddings' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/embeddings/index.js b/keras-js/src/layers/embeddings/index.js new file mode 100644 index 0000000000..c90e7c5914 --- /dev/null +++ b/keras-js/src/layers/embeddings/index.js @@ -0,0 +1,3 @@ +import Embedding from './Embedding' + +export { Embedding } diff --git a/keras-js/src/layers/index.js b/keras-js/src/layers/index.js new file mode 100644 index 0000000000..03c50c7c4a --- /dev/null +++ b/keras-js/src/layers/index.js @@ -0,0 +1,13 @@ +import InputLayer from './InputLayer' + +export { InputLayer } +export * from './advanced_activations' +export * from './convolutional' +export * from './core' +export * from './embeddings' +export * from './merge' +export * from './noise' +export * from './normalization' +export * from './pooling' +export * from './recurrent' +export * from './wrappers' diff --git a/keras-js/src/layers/merge/Add.js b/keras-js/src/layers/merge/Add.js new file mode 100644 index 0000000000..5fd37e8a0c --- /dev/null +++ b/keras-js/src/layers/merge/Add.js @@ -0,0 +1,50 @@ +import _Merge from './_Merge' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import ops from 'ndarray-ops' + +/** + * Add merge layer class, extends abstract _Merge class + */ +export default class Add extends _Merge { + /** + * Creates a Add merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Add' + + this.mode = 'sum' + } + + /** + * CPU call + * + * @param {Tensor[]} inputs + */ + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice() + this.output = new Tensor([], outputShape) + + for (let i = 0; i < inputs.length; i++) { + ops.addeq(this.output.tensor, inputs[i].tensor) + } + } + + /** + * GPU call + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape + const mergeProgramSource = createGLSLProgram('add', inputs.length, shape) + this.mergeProgram = webgl2.compileProgram(mergeProgramSource) + } + super._callGPU(inputs) + } +} diff --git a/keras-js/src/layers/merge/Average.js b/keras-js/src/layers/merge/Average.js new file mode 100644 index 0000000000..ee6a4ce06a --- /dev/null +++ b/keras-js/src/layers/merge/Average.js @@ -0,0 +1,51 @@ +import _Merge from './_Merge' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import ops from 'ndarray-ops' + +/** + * Average merge layer class, extends abstract _Merge class + */ +export default class Average extends _Merge { + /** + * Creates a Average merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Average' + + this.mode = 'ave' + } + + /** + * CPU call + * + * @param {Tensor[]} inputs + */ + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice() + this.output = new Tensor([], outputShape) + + for (let i = 0; i < inputs.length; i++) { + ops.addeq(this.output.tensor, inputs[i].tensor) + } + ops.divseq(this.output.tensor, inputs.length) + } + + /** + * GPU call + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape + const mergeProgramSource = createGLSLProgram('average', inputs.length, shape) + this.mergeProgram = webgl2.compileProgram(mergeProgramSource) + } + super._callGPU(inputs) + } +} diff --git a/keras-js/src/layers/merge/Concatenate.js b/keras-js/src/layers/merge/Concatenate.js new file mode 100644 index 0000000000..ed221b258f --- /dev/null +++ b/keras-js/src/layers/merge/Concatenate.js @@ -0,0 +1,139 @@ +import _Merge from './_Merge' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import * as tensorUtils from '../../utils/tensorUtils' +import concatFirstAxis from 'ndarray-concat-rows' +import _ from 'lodash' + +/** + * Concatenate merge layer class, extends abstract _Merge class + */ +export default class Concatenate extends _Merge { + /** + * Creates a Concatenate merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Concatenate' + + this.mode = 'concat' + + const { axis = -1 } = attrs + + // no mini-batch axis here, so we subtract 1 if given axis > 0 + this.concatAxis = axis <= 0 ? axis : axis - 1 + } + + /** + * CPU call + * + * @param {Tensor[]} inputs + */ + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice() + const _concatAxis = this.concatAxis < 0 ? outputShape.length + this.concatAxis : this.concatAxis + inputs.slice(1, inputs.length).forEach(x => { + const d = x.tensor.shape.slice()[_concatAxis] + outputShape[_concatAxis] += d + }) + this.output = new Tensor([], outputShape) + + if (_concatAxis === 0) { + concatFirstAxis(this.output.tensor, inputs.map(x => x.tensor)) + } else { + let dimsAxisSwap = [_concatAxis] + for (let i = 0; i < inputs[0].tensor.shape.length; i++) { + if (i !== _concatAxis) dimsAxisSwap.push(i) + } + concatFirstAxis( + this.output.tensor.transpose(...dimsAxisSwap), + inputs.map(x => x.tensor.transpose(...dimsAxisSwap)) + ) + } + } + + /** + * GPU call + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + }) + + const outputShape = inputs[0].glTextureShape.slice() + let _concatAxis = 1 + if (inputs[0].is2DReshaped) { + if (this.concatAxis === -1 || this.concatAxis === inputs[0].originalShape.length - 1) { + _concatAxis = 1 + } else { + this.throwError('specified axis not supported for now.') + } + } else { + if (this.concatAxis === -1 || this.concatAxis === 1) { + _concatAxis = 1 + } else if (this.concatAxis === -2 || this.concatAxis === 0) { + _concatAxis = 0 + } else { + this.throwError('specified axis not supported for now.') + } + } + + // create output textures if doesn't already exist + outputShape[_concatAxis] = _.sum(inputs.map(input => input.glTextureShape[_concatAxis])) + if (!this.output) { + this.output = new Tensor([], outputShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: _concatAxis === 1 }) + if (inputs[0].is1D) { + this.output.is1D = inputs[0].is1D + } else if (inputs[0].is2DReshaped) { + this.output.is2DReshaped = inputs[0].is2DReshaped + this.output.originalShape = inputs[0].originalShape.slice() + const _concatAxis = this.concatAxis < 0 ? this.output.originalShape.length + this.concatAxis : this.concatAxis + this.output.originalShape[_concatAxis] = _.sum(inputs.map(input => input.originalShape[_concatAxis])) + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped( + this.output.originalShape, + false, + _concatAxis + ) + } + } + + if (!this.mergeProgram) { + const outputShape = this.output.glTextureFragments + ? this.output.glTextureFragmentShape + : this.output.glTextureShape + const mergeProgramSource = createGLSLProgram( + 'concatenate', + inputs.length, + inputs.map(input => input.glTextureShape), + outputShape, + _concatAxis + ) + this.mergeProgram = webgl2.compileProgram(mergeProgramSource) + } + + webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: inputs.map((input, i) => ({ input, name: `inputs[${i}]` })), + supportsTextureFragments: true + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/merge/Dot.glsl b/keras-js/src/layers/merge/Dot.glsl new file mode 100644 index 0000000000..96a07ebcbb --- /dev/null +++ b/keras-js/src/layers/merge/Dot.glsl @@ -0,0 +1,47 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D input1; +uniform sampler2D input2; +uniform int rows; +uniform int cols; +uniform int dotAxis1; +uniform int dotAxis2; +uniform int commonDim; +uniform bool normalize; +out vec4 outColor; + +void main() { + int out_x = int(float(cols) * outTex.x); + int out_y = int(float(rows) * outTex.y); + + float sum = 0.; + float a = 0.; + float b = 0.; + float norm1 = 0.; + float norm2 = 0.; + + for (int i = 0; i < commonDim; ++i) { + if (dotAxis1 == 0 && dotAxis2 == 0) { + a = texelFetch(input1, ivec2(out_y, i), 0).r; + b = texelFetch(input2, ivec2(out_x, i), 0).r; + } else if (dotAxis1 == 1 && dotAxis2 == 1) { + a = texelFetch(input1, ivec2(i, out_y), 0).r; + b = texelFetch(input2, ivec2(i, out_x), 0).r; + } + + sum += a * b; + + if (normalize) { + norm1 += a * a; + norm2 += b * b; + } + } + + if (normalize) { + sum /= sqrt(norm1) * sqrt(norm2); + } + + outColor = vec4(sum); +} diff --git a/keras-js/src/layers/merge/Dot.js b/keras-js/src/layers/merge/Dot.js new file mode 100644 index 0000000000..4e1716feaf --- /dev/null +++ b/keras-js/src/layers/merge/Dot.js @@ -0,0 +1,133 @@ +import _Merge from './_Merge' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import gemm from 'ndarray-gemm' +import ops from 'ndarray-ops' +import mergeProgramSource from './Dot.glsl' + +/** + * Dot merge layer class, extends abstract _Merge class + */ +export default class Dot extends _Merge { + /** + * Creates a Dot merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Dot' + + this.mode = 'dot' + + const { axes = -1, normalize = false } = attrs + + // no mini-batch axis here, so we subtract 1 if given axis > 0 + if (Array.isArray(axes)) { + this.dotAxes = [axes[0] <= 0 ? axes[0] : axes[0] - 1, axes[1] <= 0 ? axes[1] : axes[1] - 1] + } else { + this.dotAxes = [axes <= 0 ? axes : axes - 1, axes <= 0 ? axes : axes - 1] + } + + this.normalize = normalize + + // GPU setup + if (this.gpu) { + this.mergeProgram = webgl2.compileProgram(mergeProgramSource) + } + } + + /** + * Calculate output shape + * + * @param {number[][]} inputShapes + */ + _calcOutputShape(inputShapes) { + let shape1 = inputShapes[0].slice() + let shape2 = inputShapes[1].slice() + shape1.splice(this.dotAxes[0], 1) + shape2.splice(this.dotAxes[1], 1) + this.outputShape = shape1.concat(shape2) + if (this.outputShape.length === 1) { + this.outputShape.push(1) + } + } + + /** + * CPU call + * + * @param {Tensor[]} inputs + */ + _callCPU(inputs) { + this._calcOutputShape([inputs[0].tensor.shape, inputs[1].tensor.shape]) + this.output = new Tensor([], this.outputShape) + + if (inputs[0].tensor.shape.length === 2 && inputs[1].tensor.shape.length === 2) { + if (this.dotAxes[0] === 0 && this.dotAxes[1] === 0) { + if (this.normalize) { + for (let i = 0; i < inputs[0].tensor.shape[1]; i++) { + ops.divseq(inputs[0].tensor.pick(null, i), ops.norm2(inputs[0].tensor.pick(null, i))) + } + for (let i = 0; i < inputs[1].tensor.shape[1]; i++) { + ops.divseq(inputs[1].tensor.pick(null, i), ops.norm2(inputs[1].tensor.pick(null, i))) + } + } + gemm(this.output.tensor, inputs[0].tensor.transpose(1, 0), inputs[1].tensor) + } else if (this.dotAxes[0] === 1 && this.dotAxes[1] === 1) { + if (this.normalize) { + for (let i = 0; i < inputs[0].tensor.shape[0]; i++) { + ops.divseq(inputs[0].tensor.pick(i, null), ops.norm2(inputs[0].tensor.pick(i, null))) + } + for (let i = 0; i < inputs[1].tensor.shape[0]; i++) { + ops.divseq(inputs[1].tensor.pick(i, null), ops.norm2(inputs[1].tensor.pick(i, null))) + } + } + gemm(this.output.tensor, inputs[0].tensor, inputs[1].tensor.transpose(1, 0)) + } + } else { + this.throwError('dot mode for 3+ dim tensors not yet implemented.') + } + } + + /** + * GPU call + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ type: '2d', format: 'float' }) + } + }) + + this._calcOutputShape([inputs[0].glTextureShape, inputs[1].glTextureShape]) + + // create output textures if doesn't already exist + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + const commonDim = inputs[0].glTextureShape[this.dotAxes[0]] + + webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: [{ input: inputs[0], name: 'input1' }, { input: inputs[1], name: 'input2' }], + uniforms: [ + { value: this.output.glTextureShape[0], type: 'int', name: 'rows' }, + { value: this.output.glTextureShape[1], type: 'int', name: 'cols' }, + { value: this.dotAxes[0], type: 'int', name: 'dotAxis1' }, + { value: this.dotAxes[1], type: 'int', name: 'dotAxis2' }, + { value: commonDim, type: 'int', name: 'commonDim' }, + { value: +this.normalize, type: 'bool', name: 'normalize' } + ] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/merge/Maximum.js b/keras-js/src/layers/merge/Maximum.js new file mode 100644 index 0000000000..e367e8d7ba --- /dev/null +++ b/keras-js/src/layers/merge/Maximum.js @@ -0,0 +1,51 @@ +import _Merge from './_Merge' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import ops from 'ndarray-ops' + +/** + * Maximum merge layer class, extends abstract _Merge class + */ +export default class Maximum extends _Merge { + /** + * Creates a Maximum merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Maximum' + + this.mode = 'max' + } + + /** + * CPU call + * + * @param {Tensor[]} inputs + */ + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice() + this.output = new Tensor([], outputShape) + + ops.assign(this.output.tensor, inputs[0].tensor) + for (let i = 1; i < inputs.length; i++) { + ops.maxeq(this.output.tensor, inputs[i].tensor) + } + } + + /** + * GPU call + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape + const mergeProgramSource = createGLSLProgram('maximum', inputs.length, shape) + this.mergeProgram = webgl2.compileProgram(mergeProgramSource) + } + super._callGPU(inputs) + } +} diff --git a/keras-js/src/layers/merge/Minimum.js b/keras-js/src/layers/merge/Minimum.js new file mode 100644 index 0000000000..c34da88f77 --- /dev/null +++ b/keras-js/src/layers/merge/Minimum.js @@ -0,0 +1,51 @@ +import _Merge from './_Merge' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import ops from 'ndarray-ops' + +/** + * Minimum merge layer class, extends abstract _Merge class + */ +export default class Minimum extends _Merge { + /** + * Creates a Minimum merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Minimum' + + this.mode = 'min' + } + + /** + * CPU call + * + * @param {Tensor[]} inputs + */ + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice() + this.output = new Tensor([], outputShape) + + ops.assign(this.output.tensor, inputs[0].tensor) + for (let i = 1; i < inputs.length; i++) { + ops.mineq(this.output.tensor, inputs[i].tensor) + } + } + + /** + * GPU call + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape + const mergeProgramSource = createGLSLProgram('minimum', inputs.length, shape) + this.mergeProgram = webgl2.compileProgram(mergeProgramSource) + } + super._callGPU(inputs) + } +} diff --git a/keras-js/src/layers/merge/Multiply.js b/keras-js/src/layers/merge/Multiply.js new file mode 100644 index 0000000000..7a4b71cc01 --- /dev/null +++ b/keras-js/src/layers/merge/Multiply.js @@ -0,0 +1,51 @@ +import _Merge from './_Merge' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import ops from 'ndarray-ops' + +/** + * Multiply merge layer class, extends abstract _Merge class + */ +export default class Multiply extends _Merge { + /** + * Creates a Multiply merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Multiply' + + this.mode = 'mul' + } + + /** + * CPU call + * + * @param {Tensor[]} inputs + */ + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice() + this.output = new Tensor([], outputShape) + + ops.assigns(this.output.tensor, 1) + for (let i = 0; i < inputs.length; i++) { + ops.muleq(this.output.tensor, inputs[i].tensor) + } + } + + /** + * GPU call + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape + const mergeProgramSource = createGLSLProgram('multiply', inputs.length, shape) + this.mergeProgram = webgl2.compileProgram(mergeProgramSource) + } + super._callGPU(inputs) + } +} diff --git a/keras-js/src/layers/merge/Subtract.js b/keras-js/src/layers/merge/Subtract.js new file mode 100644 index 0000000000..3a7d703cef --- /dev/null +++ b/keras-js/src/layers/merge/Subtract.js @@ -0,0 +1,52 @@ +import _Merge from './_Merge' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import createGLSLProgram from '../../webgl/dynamic/createGLSLProgram' +import ops from 'ndarray-ops' + +/** + * Subtract merge layer class, extends abstract _Merge class + */ +export default class Subtract extends _Merge { + /** + * Creates a Subtract merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Subtract' + + this.mode = 'diff' + } + + /** + * CPU call + * + * @param {Tensor[]} inputs + */ + _callCPU(inputs) { + if (inputs.length !== 2) { + this.throwError('Inputs should be an array of 2 Tensors.') + } + + const outputShape = inputs[0].tensor.shape.slice() + this.output = new Tensor([], outputShape) + + ops.sub(this.output.tensor, inputs[0].tensor, inputs[1].tensor) + } + + /** + * GPU call + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape + const mergeProgramSource = createGLSLProgram('subtract', inputs.length, shape) + this.mergeProgram = webgl2.compileProgram(mergeProgramSource) + } + super._callGPU(inputs) + } +} diff --git a/keras-js/src/layers/merge/_Merge.js b/keras-js/src/layers/merge/_Merge.js new file mode 100644 index 0000000000..4fd0e1293d --- /dev/null +++ b/keras-js/src/layers/merge/_Merge.js @@ -0,0 +1,135 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import _ from 'lodash' + +/** + * _Merge layer class + */ +export default class _Merge extends Layer { + /** + * Creates a _Merge layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = '_Merge' + this.isMergeLayer = true + } + + /** + * Layer computational logic + * + * @param {Tensor[]} inputs + * @returns {Tensor} + */ + call(inputs) { + if (this.gpu) { + this._callGPU(inputs) + } else { + const valid = this._validateInputs(inputs) + if (!valid) { + this.throwError('Invalid inputs to call method.') + } + this._callCPU(inputs) + } + return this.output + } + + /** + * Internal method for validating inputs + * + * @param {Tensor[]} inputs + * @returns {boolean} + */ + _validateInputs(inputs) { + const shapes = inputs.map(x => x.tensor.shape.slice()) + if (['sum', 'diff', 'mul', 'ave', 'max', 'min'].indexOf(this.mode) > -1) { + if (!shapes.every(shape => _.isEqual(shape, shapes[0]))) { + this.throwError(`All input shapes must be the same for mode ${this.mode}.`) + } + } + if (this.mode === 'dot') { + if (inputs.length !== 2) { + this.throwError(`Exactly 2 inputs required for mode ${this.mode}.`) + } + if (this.dotAxes[0] < 0) { + this.dotAxes[0] = shapes[0].length + this.dotAxes[0] + } + if (this.dotAxes[1] < 0) { + this.dotAxes[1] = shapes[1].length + this.dotAxes[1] + } + if (shapes[0][this.dotAxes[0]] !== shapes[1][this.dotAxes[1]]) { + this.throwError('Dimensions incompatibility using dot mode.') + } + } else if (this.mode === 'concat') { + let nonConcatShapes = shapes.slice() + let _concatAxis = this.concatAxis < 0 ? nonConcatShapes[0].length + this.concatAxis : this.concatAxis + if (this.concatAxis === 0) _concatAxis = 0 + _.range(nonConcatShapes.length).forEach(i => { + nonConcatShapes[i].splice(_concatAxis, 1) + }) + if (!nonConcatShapes.every(shape => _.isEqual(shape, nonConcatShapes[0]))) { + this.throwError('In concat mode, all shapes must be the same except along the concat axis.') + } + } + return true + } + + /** + * CPU call implemented in child classes + */ + _callCPU() {} + + /** + * GPU call + * + * mode: sum, diff, mul, ave, max, min + * + * method for mode concat/dot implemented in child class + * + * @param {Tensor[]} inputs + */ + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + }) + + // create output textures if doesn't already exist + if (!this.output) { + this.output = new Tensor([], inputs[0].glTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + if (inputs[0].is1D) { + this.output.is1D = inputs[0].is1D + } else if (inputs[0].is2DReshaped || inputs[0].is2DSquareReshaped) { + if (inputs[0].is2DReshaped) { + this.output.is2DReshaped = inputs[0].is2DReshaped + } else if (inputs[0].is2DSquareReshaped) { + this.output.is2DSquareReshaped = inputs[0].is2DSquareReshaped + } + this.output.originalShape = inputs[0].originalShape.slice() + this.output.indicesForReshaped = inputs[0].indicesForReshaped + } + } + + webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: inputs.map((input, i) => ({ input, name: `inputs[${i}]` })), + supportsTextureFragments: true + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/merge/index.js b/keras-js/src/layers/merge/index.js new file mode 100644 index 0000000000..331141af91 --- /dev/null +++ b/keras-js/src/layers/merge/index.js @@ -0,0 +1,10 @@ +import Add from './Add' +import Subtract from './Subtract' +import Multiply from './Multiply' +import Average from './Average' +import Maximum from './Maximum' +import Minimum from './Minimum' +import Concatenate from './Concatenate' +import Dot from './Dot' + +export { Add, Subtract, Multiply, Average, Maximum, Minimum, Concatenate, Dot } diff --git a/keras-js/src/layers/noise/GaussianDropout.js b/keras-js/src/layers/noise/GaussianDropout.js new file mode 100644 index 0000000000..d0f3da54dc --- /dev/null +++ b/keras-js/src/layers/noise/GaussianDropout.js @@ -0,0 +1,34 @@ +import Layer from '../../Layer' + +/** + * GaussianDropout layer class + * Note that this layer is here only for compatibility purposes, + * as it's only active during training phase. + */ +export default class GaussianDropout extends Layer { + /** + * Creates a GaussianDropout layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.rate] - fraction of the input units to drop (between 0 and 1) + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GaussianDropout' + + const { rate = 0.5 } = attrs + + this.rate = Math.min(Math.max(0, rate), 1) + } + + /** + * Method for layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + this.output = x + return this.output + } +} diff --git a/keras-js/src/layers/noise/GaussianNoise.js b/keras-js/src/layers/noise/GaussianNoise.js new file mode 100644 index 0000000000..99a948b386 --- /dev/null +++ b/keras-js/src/layers/noise/GaussianNoise.js @@ -0,0 +1,33 @@ +import Layer from '../../Layer' + +/** + * GaussianNoise layer class + * Note that this layer is here only for compatibility purposes, + * as it's only active during training phase. + */ +export default class GaussianNoise extends Layer { + /** + * Creates a GaussianNoise layer + * + * @param {Object} [attrs] - layer config attributes + * @param {number} [attrs.stddev] - standard deviation of the noise distribution + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GaussianNoise' + + const { stddev = 0 } = attrs + this.stddev = stddev + } + + /** + * Method for layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + this.output = x + return this.output + } +} diff --git a/keras-js/src/layers/noise/index.js b/keras-js/src/layers/noise/index.js new file mode 100644 index 0000000000..aca43c1246 --- /dev/null +++ b/keras-js/src/layers/noise/index.js @@ -0,0 +1,4 @@ +import GaussianDropout from './GaussianDropout' +import GaussianNoise from './GaussianNoise' + +export { GaussianDropout, GaussianNoise } diff --git a/keras-js/src/layers/normalization/BatchNormalization.glsl b/keras-js/src/layers/normalization/BatchNormalization.glsl new file mode 100644 index 0000000000..1416c26f59 --- /dev/null +++ b/keras-js/src/layers/normalization/BatchNormalization.glsl @@ -0,0 +1,41 @@ +#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D X; +uniform isampler2D normAxisIndexMap; +uniform sampler2D gamma; +uniform sampler2D beta; +uniform sampler2D mean; +uniform sampler2D std; +uniform float epsilon; +uniform bool scale; +uniform bool center; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(X, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + +int normAxisIndex = texelFetch(normAxisIndexMap, ivec2(out_x, out_y), 0).r; + + float _x = texelFetch(X, ivec2(out_x, out_y), 0).r; + float _mean = texelFetch(mean, ivec2(normAxisIndex, 0), 0).r; + float _std = texelFetch(std, ivec2(normAxisIndex, 0), 0).r; + + float _gamma = 1.0; + if (scale) { + _gamma = texelFetch(gamma, ivec2(normAxisIndex, 0), 0).r; + } + + float _beta = 0.0; + if (center) { + _beta = texelFetch(beta, ivec2(normAxisIndex, 0), 0).r; + } + + float sum = _beta + _gamma * (_x - _mean) / sqrt(_std + epsilon); + + outColor = vec4(sum); +} diff --git a/keras-js/src/layers/normalization/BatchNormalization.js b/keras-js/src/layers/normalization/BatchNormalization.js new file mode 100644 index 0000000000..5493437907 --- /dev/null +++ b/keras-js/src/layers/normalization/BatchNormalization.js @@ -0,0 +1,224 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import programSource from './BatchNormalization.glsl' + +/** + * BatchNormalization layer class + */ +export default class BatchNormalization extends Layer { + /** + * Creates an BatchNormalization layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'BatchNormalization' + + const { epsilon = 0.001, axis = -1, center = true, scale = true } = attrs + + this.epsilon = epsilon + this.center = center + this.scale = scale + + // no batch axis, so axis is less 1 compared to representation in keras + // will be set in call(), as input tensor shape is needed to calculate axis + // if axis < 0 + this.axis = axis + this.axisNormalized = false + + // Layer weights specification + this.params = [] + if (this.scale) { + this.params.push('gamma') + } + if (this.center) { + this.params.push('beta') + } + this.params = this.params.concat(['moving_mean', 'moving_variance']) + + // GPU setup + if (this.gpu) { + this.program = webgl2.compileProgram(programSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + if (!this.axisNormalized) { + this.axis = this.axis < 0 ? x.tensor.shape.length + this.axis : this.axis - 1 + this.axisNormalized = true + } + + let broadcast = [] + for (let d = 0; d < x.tensor.shape.length; d++) { + if (d === this.axis) broadcast.push(1) + else broadcast.push(null) + } + + // broadcast weights + let _gamma = new Tensor([], x.tensor.shape) + let _beta = new Tensor([], x.tensor.shape) + for (let i = 0; i < x.tensor.shape[this.axis]; i++) { + broadcast[this.axis] = i + if (this.scale) { + ops.assigns(_gamma.tensor.pick(...broadcast), this.weights['gamma'].tensor.get(i)) + } + if (this.center) { + ops.assigns(_beta.tensor.pick(...broadcast), this.weights['beta'].tensor.get(i)) + } + } + + let _mean = new Tensor([], x.tensor.shape) + let _std = new Tensor([], x.tensor.shape) + + // feature-wise normalization + for (let i = 0; i < x.tensor.shape[this.axis]; i++) { + broadcast[this.axis] = i + ops.assigns(_mean.tensor.pick(...broadcast), this.weights['moving_mean'].tensor.get(i)) + ops.assigns(_std.tensor.pick(...broadcast), this.weights['moving_variance'].tensor.get(i) + this.epsilon) + } + ops.sqrteq(_std.tensor) + + this.output = new Tensor(x.tensor.data, x.tensor.shape) + + ops.subeq(this.output.tensor, _mean.tensor) + ops.diveq(this.output.tensor, _std.tensor) + if (this.scale) { + ops.muleq(this.output.tensor, _gamma.tensor) + } + if (this.center) { + ops.addeq(this.output.tensor, _beta.tensor) + } + } + + /** + * Pre-compute index maps for GPU batchnorm function + * + * @param {number[]} glTextureShape + * @param {Object} indicesForReshaped + */ + _createIndexMap(glTextureShape, indicesForReshaped) { + if (this.normAxisIndexMap) { + return + } + + const _normAxisIndexMap = new Tensor([], this.inputShape, { type: Int32Array }) + this.normAxisIndexMap = new Tensor([], glTextureShape, { type: Int32Array }) + + const slice = Array(this.inputShape.length).fill(null) + for (let i = 0; i < this.inputShape[this.axis]; i++) { + slice[this.axis] = i + ops.assigns(_normAxisIndexMap.tensor.pick(...slice), i) + } + + if (indicesForReshaped) { + for (let i = 0; i < indicesForReshaped.data.length; i++) { + this.normAxisIndexMap.tensor.data[indicesForReshaped.data[i]] = _normAxisIndexMap.tensor.data[i] + } + } else { + this.normAxisIndexMap = _normAxisIndexMap + } + + this.normAxisIndexMap.createGLTexture({ type: '2d', format: 'int', supportsTextureFragments: true }) + } + + /** + * GPU call + * (will only work on the 2D-reshaped representation for post-convolutional BN) + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!this.axisNormalized) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + this.inputShape = x.tensor.shape + } + this.axis = this.axis < 0 ? this.inputShape.length + this.axis : this.axis - 1 + this.axisNormalized = true + } + + if (!x.glTexture && !x.glTextureFragments) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2DSquare() + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + } + + this._createIndexMap(x.glTextureShape, x.indicesForReshaped) + + // create output textures if doesn't already exist + if (!this.output) { + this.output = new Tensor([], x.glTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + if (x.is1D) { + this.output.is1D = x.is1D + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped + } + this.output.originalShape = x.originalShape + this.output.indicesForReshaped = x.indicesForReshaped + } + } + + const programInputs = [{ input: x, name: 'X' }, { input: this.normAxisIndexMap, name: 'normAxisIndexMap' }] + if (this.scale) { + programInputs.push({ input: this.weights['gamma'], name: 'gamma' }) + } + if (this.center) { + programInputs.push({ input: this.weights['beta'], name: 'beta' }) + } + programInputs.push({ input: this.weights['moving_mean'], name: 'mean' }) + programInputs.push({ input: this.weights['moving_variance'], name: 'std' }) + const programUniforms = [ + { value: this.epsilon, type: 'float', name: 'epsilon' }, + { value: +this.scale, type: 'bool', name: 'scale' }, + { value: +this.center, type: 'bool', name: 'center' } + ] + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: programInputs, + uniforms: programUniforms, + supportsTextureFragments: true + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/normalization/index.js b/keras-js/src/layers/normalization/index.js new file mode 100644 index 0000000000..ddcbf46e01 --- /dev/null +++ b/keras-js/src/layers/normalization/index.js @@ -0,0 +1,3 @@ +import BatchNormalization from './BatchNormalization' + +export { BatchNormalization } diff --git a/keras-js/src/layers/pooling/AveragePooling1D.js b/keras-js/src/layers/pooling/AveragePooling1D.js new file mode 100644 index 0000000000..6d8a319062 --- /dev/null +++ b/keras-js/src/layers/pooling/AveragePooling1D.js @@ -0,0 +1,16 @@ +import _Pooling1D from './_Pooling1D' + +/** + * AveragePooling1D layer class, extends abstract _Pooling1D class + */ +export default class AveragePooling1D extends _Pooling1D { + /** + * Creates a AveragePooling1D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'AveragePooling1D' + + this.poolingFunc = 'average' + } +} diff --git a/keras-js/src/layers/pooling/AveragePooling2D.js b/keras-js/src/layers/pooling/AveragePooling2D.js new file mode 100644 index 0000000000..c1feb3be6f --- /dev/null +++ b/keras-js/src/layers/pooling/AveragePooling2D.js @@ -0,0 +1,16 @@ +import _Pooling2D from './_Pooling2D' + +/** + * AveragePooling2D layer class, extends abstract _Pooling2D class + */ +export default class AveragePooling2D extends _Pooling2D { + /** + * Creates a AveragePooling2D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'AveragePooling2D' + + this.poolingFunc = 'average' + } +} diff --git a/keras-js/src/layers/pooling/AveragePooling3D.js b/keras-js/src/layers/pooling/AveragePooling3D.js new file mode 100644 index 0000000000..9d9dacc6e6 --- /dev/null +++ b/keras-js/src/layers/pooling/AveragePooling3D.js @@ -0,0 +1,16 @@ +import _Pooling3D from './_Pooling3D' + +/** + * AveragePooling3D layer class, extends abstract _Pooling3D class + */ +export default class AveragePooling3D extends _Pooling3D { + /** + * Creates a AveragePooling3D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'AveragePooling3D' + + this.poolingFunc = 'average' + } +} diff --git a/keras-js/src/layers/pooling/GlobalAveragePooling1D.js b/keras-js/src/layers/pooling/GlobalAveragePooling1D.js new file mode 100644 index 0000000000..f49d6b4e03 --- /dev/null +++ b/keras-js/src/layers/pooling/GlobalAveragePooling1D.js @@ -0,0 +1,16 @@ +import _GlobalPooling1D from './_GlobalPooling1D' + +/** + * GlobalAveragePooling1D layer class, extends abstract _GlobalPooling1D class + */ +export default class GlobalAveragePooling1D extends _GlobalPooling1D { + /** + * Creates a GlobalAveragePooling1D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GlobalAveragePooling1D' + + this.poolingFunc = 'average' + } +} diff --git a/keras-js/src/layers/pooling/GlobalAveragePooling2D.js b/keras-js/src/layers/pooling/GlobalAveragePooling2D.js new file mode 100644 index 0000000000..c1b00d8d47 --- /dev/null +++ b/keras-js/src/layers/pooling/GlobalAveragePooling2D.js @@ -0,0 +1,16 @@ +import _GlobalPooling2D from './_GlobalPooling2D' + +/** + * GlobalAveragePooling2D layer class, extends abstract _GlobalPooling2D class + */ +export default class GlobalAveragePooling2D extends _GlobalPooling2D { + /** + * Creates a GlobalAveragePooling2D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GlobalAveragePooling2D' + + this.poolingFunc = 'average' + } +} diff --git a/keras-js/src/layers/pooling/GlobalAveragePooling3D.js b/keras-js/src/layers/pooling/GlobalAveragePooling3D.js new file mode 100644 index 0000000000..381342c392 --- /dev/null +++ b/keras-js/src/layers/pooling/GlobalAveragePooling3D.js @@ -0,0 +1,16 @@ +import _GlobalPooling3D from './_GlobalPooling3D' + +/** + * GlobalAveragePooling3D layer class, extends abstract _GlobalPooling3D class + */ +export default class GlobalAveragePooling3D extends _GlobalPooling3D { + /** + * Creates a GlobalAveragePooling3D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GlobalAveragePooling3D' + + this.poolingFunc = 'average' + } +} diff --git a/keras-js/src/layers/pooling/GlobalMaxPooling1D.js b/keras-js/src/layers/pooling/GlobalMaxPooling1D.js new file mode 100644 index 0000000000..7762fdf24c --- /dev/null +++ b/keras-js/src/layers/pooling/GlobalMaxPooling1D.js @@ -0,0 +1,16 @@ +import _GlobalPooling1D from './_GlobalPooling1D' + +/** + * GlobalMaxPooling1D layer class, extends abstract _GlobalPooling1D class + */ +export default class GlobalMaxPooling1D extends _GlobalPooling1D { + /** + * Creates a GlobalMaxPooling1D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GlobalMaxPooling1D' + + this.poolingFunc = 'max' + } +} diff --git a/keras-js/src/layers/pooling/GlobalMaxPooling2D.js b/keras-js/src/layers/pooling/GlobalMaxPooling2D.js new file mode 100644 index 0000000000..b39da24a65 --- /dev/null +++ b/keras-js/src/layers/pooling/GlobalMaxPooling2D.js @@ -0,0 +1,16 @@ +import _GlobalPooling2D from './_GlobalPooling2D' + +/** + * GlobalMaxPooling2D layer class, extends abstract _GlobalPooling2D class + */ +export default class GlobalMaxPooling2D extends _GlobalPooling2D { + /** + * Creates a GlobalMaxPooling2D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GlobalMaxPooling2D' + + this.poolingFunc = 'max' + } +} diff --git a/keras-js/src/layers/pooling/GlobalMaxPooling3D.js b/keras-js/src/layers/pooling/GlobalMaxPooling3D.js new file mode 100644 index 0000000000..9c7bdd26a6 --- /dev/null +++ b/keras-js/src/layers/pooling/GlobalMaxPooling3D.js @@ -0,0 +1,16 @@ +import _GlobalPooling3D from './_GlobalPooling3D' + +/** + * GlobalMaxPooling3D layer class, extends abstract _GlobalPooling3D class + */ +export default class GlobalMaxPooling3D extends _GlobalPooling3D { + /** + * Creates a GlobalMaxPooling3D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GlobalMaxPooling3D' + + this.poolingFunc = 'max' + } +} diff --git a/keras-js/src/layers/pooling/MaxPooling1D.js b/keras-js/src/layers/pooling/MaxPooling1D.js new file mode 100644 index 0000000000..d43b883d2c --- /dev/null +++ b/keras-js/src/layers/pooling/MaxPooling1D.js @@ -0,0 +1,16 @@ +import _Pooling1D from './_Pooling1D' + +/** + * MaxPooling1D layer class, extends abstract _Pooling1D class + */ +export default class MaxPooling1D extends _Pooling1D { + /** + * Creates a MaxPooling1D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'MaxPooling1D' + + this.poolingFunc = 'max' + } +} diff --git a/keras-js/src/layers/pooling/MaxPooling2D.js b/keras-js/src/layers/pooling/MaxPooling2D.js new file mode 100644 index 0000000000..bb470ca3fa --- /dev/null +++ b/keras-js/src/layers/pooling/MaxPooling2D.js @@ -0,0 +1,16 @@ +import _Pooling2D from './_Pooling2D' + +/** + * MaxPooling2D layer class, extends abstract _Pooling2D class + */ +export default class MaxPooling2D extends _Pooling2D { + /** + * Creates a MaxPooling2D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'MaxPooling2D' + + this.poolingFunc = 'max' + } +} diff --git a/keras-js/src/layers/pooling/MaxPooling3D.js b/keras-js/src/layers/pooling/MaxPooling3D.js new file mode 100644 index 0000000000..8c4a9cec55 --- /dev/null +++ b/keras-js/src/layers/pooling/MaxPooling3D.js @@ -0,0 +1,16 @@ +import _Pooling3D from './_Pooling3D' + +/** + * MaxPooling3D layer class, extends abstract _Pooling3D class + */ +export default class MaxPooling3D extends _Pooling3D { + /** + * Creates a MaxPooling3D layer + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'MaxPooling3D' + + this.poolingFunc = 'max' + } +} diff --git a/keras-js/src/layers/pooling/_GlobalPooling.glsl b/keras-js/src/layers/pooling/_GlobalPooling.glsl new file mode 100644 index 0000000000..c8a6cf55ac --- /dev/null +++ b/keras-js/src/layers/pooling/_GlobalPooling.glsl @@ -0,0 +1,34 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform int channelDataSize; +uniform bool isMaxPooling; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(x, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + if (isMaxPooling) { + // GlobalMaxPooling + float maxval = 0.0; + for (int j = 0; j < size[1]; ++j) { + float val = texelFetch(x, ivec2(out_x, j), 0).r; + if (j == 0 || val > maxval) { + maxval = val; + } + } + outColor = vec4(maxval); + } else { + // GlobalAveragePooling + float sum = 0.0; + for (int j = 0; j < size[1]; ++j) { + float val = texelFetch(x, ivec2(out_x, j), 0).r; + sum += val; + } + outColor = vec4(sum / float(channelDataSize)); + } +} diff --git a/keras-js/src/layers/pooling/_GlobalPooling1D.js b/keras-js/src/layers/pooling/_GlobalPooling1D.js new file mode 100644 index 0000000000..4b370a0fe6 --- /dev/null +++ b/keras-js/src/layers/pooling/_GlobalPooling1D.js @@ -0,0 +1,100 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import poolingProgramSource from './_GlobalPooling.glsl' + +/** + * _GlobalPooling1D layer class + */ +export default class _GlobalPooling1D extends Layer { + /** + * Creates a _GlobalPooling1D layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = '_GlobalPooling1D' + + const { data_format = 'channels_last' } = attrs + this.dataFormat = data_format + + // default pooling function + // can be `max` or `average` + this.poolingFunc = 'max' + + // GPU setup + if (this.gpu) { + this.poolingProgram = webgl2.compileProgram(poolingProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + const [steps, features] = x.tensor.shape + this.output = new Tensor([], [features]) + for (let i = 0, len = features; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, ops.sup(x.tensor.pick(null, i))) + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, ops.sum(x.tensor.pick(null, i)) / steps) + } + } + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + this.inputShape = x.tensor.shape + + // create output textures if doesn't already exist + if (!this.output) { + this.output = new Tensor([], [this.inputShape[1]]) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + // `true` if max pooling, `false` if average pooling + const isMaxPooling = this.poolingFunc === 'max' + + webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }], + uniforms: [ + { value: this.inputShape[0], type: 'int', name: 'channelDataSize' }, + { value: +isMaxPooling, type: 'bool', name: 'isMaxPooling' } + ] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/pooling/_GlobalPooling2D.js b/keras-js/src/layers/pooling/_GlobalPooling2D.js new file mode 100644 index 0000000000..50c9902274 --- /dev/null +++ b/keras-js/src/layers/pooling/_GlobalPooling2D.js @@ -0,0 +1,112 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import poolingProgramSource from './_GlobalPooling.glsl' + +/** + * _GlobalPooling2D layer class + */ +export default class _GlobalPooling2D extends Layer { + /** + * Creates a _GlobalPooling2D layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = '_GlobalPooling2D' + + const { data_format = 'channels_last' } = attrs + this.dataFormat = data_format + + // default pooling function + // can be `max` or `average` + this.poolingFunc = 'max' + + // GPU setup + if (this.gpu) { + this.poolingProgram = webgl2.compileProgram(poolingProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0) + } + + const [rows, cols, channels] = x.tensor.shape + this.output = new Tensor([], [channels]) + for (let i = 0, len = channels; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, ops.sup(x.tensor.pick(null, null, i))) + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, ops.sum(x.tensor.pick(null, null, i)) / (rows * cols)) + } + } + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + // convert to channels_last ordering + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0) + } + this.inputShape = x.tensor.shape + x.reshapeTo2D() + x.createGLTexture({ type: '2d', format: 'float' }) + } + + // create output textures if doesn't already exist + if (!this.output) { + this.output = new Tensor([], [this.inputShape[2]]) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + // `true` if max pooling, `false` if average pooling + const isMaxPooling = this.poolingFunc === 'max' + + webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }], + uniforms: [ + { value: this.inputShape[0] * this.inputShape[1], type: 'int', name: 'channelDataSize' }, + { value: +isMaxPooling, type: 'bool', name: 'isMaxPooling' } + ] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/pooling/_GlobalPooling3D.js b/keras-js/src/layers/pooling/_GlobalPooling3D.js new file mode 100644 index 0000000000..b01147c087 --- /dev/null +++ b/keras-js/src/layers/pooling/_GlobalPooling3D.js @@ -0,0 +1,112 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import poolingProgramSource from './_GlobalPooling.glsl' + +/** + * _GlobalPooling3D layer class + */ +export default class _GlobalPooling3D extends Layer { + /** + * Creates a _GlobalPooling3D layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = '_GlobalPooling3D' + + const { data_format = 'channels_last' } = attrs + this.dataFormat = data_format + + // default pooling function + // can be `max` or `average` + this.poolingFunc = 'max' + + // GPU setup + if (this.gpu) { + this.poolingProgram = webgl2.compileProgram(poolingProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0) + } + + const [dim1, dim2, dim3, channels] = x.tensor.shape + this.output = new Tensor([], [channels]) + for (let i = 0, len = channels; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, ops.sup(x.tensor.pick(null, null, null, i))) + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, ops.sum(x.tensor.pick(null, null, null, i)) / (dim1 * dim2 * dim3)) + } + } + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + // convert to channels_last ordering + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0) + } + this.inputShape = x.tensor.shape + x.reshapeTo2D() + x.createGLTexture({ type: '2d', format: 'float' }) + } + + // create output textures if doesn't already exist + if (!this.output) { + this.output = new Tensor([], [this.inputShape[3]]) + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + // `true` if max pooling, `false` if average pooling + const isMaxPooling = this.poolingFunc === 'max' + + webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }], + uniforms: [ + { value: this.inputShape[0] * this.inputShape[1] * this.inputShape[2], type: 'int', name: 'channelDataSize' }, + { value: +isMaxPooling, type: 'bool', name: 'isMaxPooling' } + ] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/pooling/_Pooling.fragments.glsl b/keras-js/src/layers/pooling/_Pooling.fragments.glsl new file mode 100644 index 0000000000..d1ad440170 --- /dev/null +++ b/keras-js/src/layers/pooling/_Pooling.fragments.glsl @@ -0,0 +1,43 @@ +#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D x; +uniform isampler2D poolIndexMap; +uniform int channels; +uniform int poolSize; +uniform bool isMaxPooling; +out vec4 outColor; + +void main() { + ivec2 inputSize = textureSize(x, 0); + ivec2 outputSize = textureSize(poolIndexMap, 0); + int out_x = int(float(channels) * outTex.x); + int out_y = int(float(outputSize[1]) * outTex.y); + + float val = 0.; + int count = 0; + for (int i = 0; i < poolSize; ++i) { + int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r; + int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1]))); + if (poolIndex != -1) { + poolIndex = int(mod(float(poolIndex), float(inputSize[1]))); + float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r; + if (isMaxPooling) { + if (count == 0 || val2 > val) { + val = val2; + } + } else { + val += val2; + } + count += 1; + } + } + + if (!isMaxPooling) { + val /= float(count); + } + + outColor = vec4(val); +} diff --git a/keras-js/src/layers/pooling/_Pooling.glsl b/keras-js/src/layers/pooling/_Pooling.glsl new file mode 100644 index 0000000000..92726cd49a --- /dev/null +++ b/keras-js/src/layers/pooling/_Pooling.glsl @@ -0,0 +1,39 @@ +#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D x; +uniform isampler2D poolIndexMap; +uniform int channels; +uniform int poolSize; +uniform bool isMaxPooling; +out vec4 outColor; + +void main() { + int out_x = int(float(channels) * outTex.x); + int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y); + + float val = 0.; + int count = 0; + for (int i = 0; i < poolSize; ++i) { + int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r; + if (poolIndex != -1) { + float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r; + if (isMaxPooling) { + if (count == 0 || val2 > val) { + val = val2; + } + } else { + val += val2; + } + count += 1; + } + } + + if (!isMaxPooling) { + val /= float(count); + } + + outColor = vec4(val); +} diff --git a/keras-js/src/layers/pooling/_Pooling1D.js b/keras-js/src/layers/pooling/_Pooling1D.js new file mode 100644 index 0000000000..dcc39d5491 --- /dev/null +++ b/keras-js/src/layers/pooling/_Pooling1D.js @@ -0,0 +1,195 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import poolingProgramSource from './_Pooling.glsl' +import poolingFragmentsProgramSource from './_Pooling.fragments.glsl' + +/** + * _Pooling1D layer class + */ +export default class _Pooling1D extends Layer { + /** + * Creates a _Pooling1D layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = '_Pooling1D' + + const { pool_size = 2, strides = null, padding = 'valid' } = attrs + + this.poolSize = pool_size + this.strides = strides === null ? this.poolSize : strides + this.padding = padding + + // default pooling function + // can be `max` or `average` + this.poolingFunc = 'max' + + // GPU setup + if (this.gpu) { + this.poolingProgram = webgl2.compileProgram(poolingProgramSource) + this.poolingFragmentsProgram = webgl2.compileProgram(poolingFragmentsProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + const stepsNew = + this.padding === 'valid' + ? Math.floor((x.tensor.shape[0] - this.poolSize + this.strides) / this.strides) + : Math.floor((x.tensor.shape[0] + this.strides - 1) / this.strides) + + this.output = new Tensor([], [stepsNew, x.tensor.shape[1]]) + const outputStep = new Tensor([], [x.tensor.shape[1]]) + + // in padding same, start negative from beyond step 0 + let step = + this.padding === 'valid' + ? 0 + : Math.min(0, Math.ceil((x.tensor.shape[0] - (stepsNew - 1) * this.strides - this.poolSize) / 2)) + + for (let i = 0; i < stepsNew; i++) { + let _step = Math.max(0, step) + let limit = this.poolSize + Math.min(0, step) + ops.assign(outputStep.tensor, x.tensor.pick(_step, null)) + + let count = 1 + for (let j = 1; j < limit; j++) { + if (_step + j > x.tensor.shape[0] - 1) { + break + } + if (this.poolingFunc === 'max') { + ops.maxeq(outputStep.tensor, x.tensor.pick(_step + j, null)) + } else if (this.poolingFunc === 'average') { + ops.addeq(outputStep.tensor, x.tensor.pick(_step + j, null)) + } + count += 1 + } + + if (this.poolingFunc === 'average') { + ops.divseq(outputStep.tensor, count) + } + + ops.assign(this.output.tensor.pick(i, null), outputStep.tensor) + step += this.strides + } + } + + /** + * Pre-compute index map for GPU pooling function + */ + _createIndexMap() { + if (this.poolIndexMap) { + return + } + + const stepsNew = + this.padding === 'valid' + ? Math.floor((this.inputShape[0] - this.poolSize + this.strides) / this.strides) + : Math.floor((this.inputShape[0] + this.strides - 1) / this.strides) + + this.outputShape = [stepsNew, this.inputShape[1]] + + this.poolIndexMap = new Tensor([], [stepsNew, this.poolSize], { type: Int32Array }) + ops.assigns(this.poolIndexMap.tensor, -1) + + // in padding same, start negative from beyond step 0 + let step = + this.padding === 'valid' + ? 0 + : Math.min(0, Math.ceil((this.inputShape[0] - (stepsNew - 1) * this.strides - this.poolSize) / 2)) + + for (let i = 0; i < stepsNew; i++) { + let _step = Math.max(0, step) + let limit = this.poolSize + Math.min(0, step) + + let inputIndex = _step + this.poolIndexMap.tensor.set(i, 0, inputIndex) + for (let j = 1; j < limit; j++) { + inputIndex = _step + j + if (inputIndex <= this.inputShape[0] - 1) { + this.poolIndexMap.tensor.set(i, j, inputIndex) + } else { + break + } + } + step += this.strides + } + + this.poolIndexMap.createGLTexture({ type: '2d', format: 'int', supportsTextureFragments: true }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + this.inputShape = x.tensor.shape + this._createIndexMap() + + // create output textures if doesn't already exist + if (!this.output) { + this.output = new Tensor([], this.outputShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + + // `true` if max pooling, `false` if average pooling + const isMaxPooling = this.poolingFunc === 'max' + + const programUniforms = [ + { value: this.output.glTextureShape[1], type: 'int', name: 'channels' }, + { value: this.poolSize, type: 'int', name: 'poolSize' }, + { value: +isMaxPooling, type: 'bool', name: 'isMaxPooling' } + ] + if (x.glTextureFragments) { + x.convert2DRowFragmentedGLTextureToColStack() + webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.poolIndexMap, name: 'poolIndexMap' }], + uniforms: programUniforms, + supportsTextureFragments: true + }) + x.removeGLTextureFragmentsAsColStack() + } else { + webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ input: x, name: 'x' }, { input: this.poolIndexMap, name: 'poolIndexMap' }], + uniforms: programUniforms, + supportsTextureFragments: true + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/pooling/_Pooling2D.js b/keras-js/src/layers/pooling/_Pooling2D.js new file mode 100644 index 0000000000..8469816c2c --- /dev/null +++ b/keras-js/src/layers/pooling/_Pooling2D.js @@ -0,0 +1,343 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import * as tensorUtils from '../../utils/tensorUtils' +import ops from 'ndarray-ops' +import poolingProgramSource from './_Pooling.glsl' +import poolingFragmentsProgramSource from './_Pooling.fragments.glsl' + +/** + * _Pooling2D layer class + */ +export default class _Pooling2D extends Layer { + /** + * Creates a _Pooling2D layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = '_Pooling2D' + + const { pool_size = [2, 2], strides = null, padding = 'valid', data_format = 'channels_last' } = attrs + + if (Array.isArray(pool_size)) { + this.poolSize = pool_size + } else { + this.poolSize = [pool_size, pool_size] + } + + if (Array.isArray(strides)) { + this.strides = strides + } else if (strides !== null) { + this.strides = [strides, strides] + } else { + this.strides = this.poolSize + } + + this.padding = padding + this.dataFormat = data_format + + // default pooling function + // can be `max` or `average` + this.poolingFunc = 'max' + + // GPU setup + if (this.gpu) { + this.poolingProgram = webgl2.compileProgram(poolingProgramSource) + this.poolingFragmentsProgram = webgl2.compileProgram(poolingFragmentsProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * Method for computing output dimensions and padding, based on input dimensions, kernel size, and padding mode + * + * For tensorflow implementation of padding, see: + * https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/common_shape_fns.cc + + * @param {number[]} inputShape + */ + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return + } + + const [inputRows, inputCols, inputChannels] = inputShape + const [nbRow, nbCol] = this.poolSize + + const outputRows = + this.padding === 'same' + ? Math.floor((inputRows + this.strides[0] - 1) / this.strides[0]) + : Math.floor((inputRows - nbRow + this.strides[0]) / this.strides[0]) + const outputCols = + this.padding === 'same' + ? Math.floor((inputCols + this.strides[1] - 1) / this.strides[1]) + : Math.floor((inputCols - nbCol + this.strides[1]) / this.strides[1]) + + const paddingRow = + this.padding === 'same' ? Math.max(0, Math.floor((outputRows - 1) * this.strides[0] + nbRow - inputRows)) : 0 + const paddingCol = + this.padding === 'same' ? Math.max(0, Math.floor((outputCols - 1) * this.strides[1] + nbCol - inputCols)) : 0 + const paddingRowBefore = Math.floor(paddingRow / 2) + const paddingRowAfter = paddingRow - paddingRowBefore + const paddingColBefore = Math.floor(paddingCol / 2) + const paddingColAfter = paddingCol - paddingColBefore + + this.outputShape = [outputRows, outputCols, inputChannels] + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] + } + + /** + * Pad input tensor if necessary, for padding='same'. See above for notes on calculating padding. + * For max, we pad with -infinity. + * + * For average we pad with zero. + * + * @param {Tensor} x + * @returns {Tensor} + */ + _padInput(x) { + if (this.padding === 'same') { + const [inputRows, inputCols, inputChannels] = x.tensor.shape + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding + const newRows = inputRows + paddingRowBefore + paddingRowAfter + const newCols = inputCols + paddingColBefore + paddingColAfter + + const _x = new Tensor([], [newRows, newCols, inputChannels]) + if (this.poolingFunc === 'max') { + ops.assigns(_x.tensor, Number.NEGATIVE_INFINITY) + } + + ops.assign( + _x.tensor + .hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels) + .lo(paddingRowBefore, paddingColBefore, 0), + x.tensor + ) + return _x + } + return x + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0) + } + + this._calcOutputShape(x.tensor.shape) + x = this._padInput(x) + + const [inputRows, inputCols, inputChannels] = x.tensor.shape + const [nbRow, nbCol] = this.poolSize + this.output = new Tensor([], this.outputShape) + const patch = new Tensor([], [nbRow, nbCol, inputChannels]) + + // keep track of padding since these values are not included in pooling + // for max, we can ignore since padding values are set to -infinity + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding + + for (let i = 0, _i = 0; i <= inputRows - nbRow; i += this.strides[0], _i++) { + let nbRowInPadding = 0 + if (i < paddingRowBefore) { + nbRowInPadding = paddingRowBefore - i + } else if (i + nbRow > inputRows - paddingRowAfter) { + nbRowInPadding = i + nbRow - (inputRows - paddingRowAfter) + } + + for (let j = 0, _j = 0; j <= inputCols - nbCol; j += this.strides[1], _j++) { + let nbColInPadding = 0 + if (j < paddingColBefore) { + nbColInPadding = paddingColBefore - j + } else if (j + nbCol > inputCols - paddingColAfter) { + nbColInPadding = j + nbCol - (inputCols - paddingColAfter) + } + const nbCellsEffective = (nbRow - nbRowInPadding) * (nbCol - nbColInPadding) + + ops.assign(patch.tensor, x.tensor.hi(i + nbRow, j + nbCol, inputChannels).lo(i, j, 0)) + for (let c = 0; c < inputChannels; c++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(_i, _j, c, ops.sup(patch.tensor.pick(null, null, c))) + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(_i, _j, c, ops.sum(patch.tensor.pick(null, null, c)) / nbCellsEffective) + } + } + } + } + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + + /** + * Convert input tensor to column matrix + * + * @param {Tensor} x + * @returns {Tensor} + */ + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape + if (!this.tiledInput) { + this.tiledInput = new Tensor([], [inputRows * inputCols, inputChannels]) + } + + const patch = new Tensor([], [inputRows, inputCols]) + const patchRaveled = new Tensor([], [inputRows * inputCols]) + for (let c = 0; c < inputChannels; c++) { + ops.assign(patch.tensor, x.tensor.pick(null, null, c)) + patchRaveled.replaceTensorData(patch.tensor.data) + ops.assign(this.tiledInput.tensor.pick(null, c), patchRaveled.tensor) + } + + return this.tiledInput + } + + /** + * Pre-compute index map for GPU pooling function + */ + _createIndexMap() { + if (this.poolIndexMap) { + return + } + + let inputRows = this.inputShape[0] + let inputCols = this.inputShape[1] + const rowIndices = new Tensor([], [inputRows, inputCols]) + let index = 0 + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + rowIndices.tensor.set(i, j, index) + index += 1 + } + } + + // padding for border mode 'same' + if (this.padding === 'same') { + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding + inputRows = inputRows + paddingRowBefore + paddingRowAfter + inputCols = inputCols + paddingColBefore + paddingColAfter + const _rowIndices = new Tensor([], [inputRows, inputCols]) + ops.assigns(_rowIndices.tensor, -1) + ops.assign( + _rowIndices.tensor + .hi(this.inputShape[0] + paddingRowBefore, this.inputShape[1] + paddingColBefore) + .lo(paddingRowBefore, paddingColBefore), + rowIndices.tensor + ) + rowIndices.tensor = _rowIndices.tensor + } + + const [nbRow, nbCol] = this.poolSize + const outputRows = this.outputShape[0] + const outputCols = this.outputShape[1] + + this.poolIndexMap = new Tensor([], [outputRows * outputCols, nbRow * nbCol], { type: Int32Array }) + + const patchRow = new Tensor([], [nbRow, nbCol]) + let offset = 0 + for (let i = 0, limit = inputRows - nbRow; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbCol; j <= limit; j += this.strides[1]) { + ops.assign(patchRow.tensor, rowIndices.tensor.hi(i + nbRow, j + nbCol).lo(i, j)) + this.poolIndexMap.tensor.data.set(patchRow.tensor.data, offset) + offset += nbRow * nbCol + } + } + + this.poolIndexMap.createGLTexture({ type: '2d', format: 'int', supportsTextureFragments: true }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + // convert to channels_last ordering + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0) + } + this.inputShape = x.tensor.shape + this._im2col(x) + this.tiledInput.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + this._calcOutputShape(this.inputShape) + this._createIndexMap() + + // create output textures if doesn't already exist + if (!this.output) { + const [outputRows, outputCols, inputChannels] = this.outputShape + const outputTextureShape = [outputRows * outputCols, inputChannels] + this.output = new Tensor([], outputTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.output.is2DReshaped = true + this.output.originalShape = this.outputShape + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.tiledInput + const poolSize = this.poolSize[0] * this.poolSize[1] + // `true` if max pooling, `false` if average pooling + const isMaxPooling = this.poolingFunc === 'max' + + const programUniforms = [ + { value: this.output.glTextureShape[1], type: 'int', name: 'channels' }, + { value: poolSize, type: 'int', name: 'poolSize' }, + { value: +isMaxPooling, type: 'bool', name: 'isMaxPooling' } + ] + if (input.glTextureFragments) { + input.convert2DRowFragmentedGLTextureToColStack() + webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ input: input, name: 'x' }, { input: this.poolIndexMap, name: 'poolIndexMap' }], + uniforms: programUniforms, + supportsTextureFragments: true + }) + input.removeGLTextureFragmentsAsColStack() + } else { + webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ input: input, name: 'x' }, { input: this.poolIndexMap, name: 'poolIndexMap' }], + uniforms: programUniforms, + supportsTextureFragments: true + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2D() + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1) + } + } + } +} diff --git a/keras-js/src/layers/pooling/_Pooling3D.js b/keras-js/src/layers/pooling/_Pooling3D.js new file mode 100644 index 0000000000..bd8acd2a13 --- /dev/null +++ b/keras-js/src/layers/pooling/_Pooling3D.js @@ -0,0 +1,407 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import * as tensorUtils from '../../utils/tensorUtils' +import ops from 'ndarray-ops' +import poolingProgramSource from './_Pooling.glsl' +import poolingFragmentsProgramSource from './_Pooling.fragments.glsl' + +/** + * _Pooling3D layer class + */ +export default class _Pooling3D extends Layer { + /** + * Creates a _Pooling3D layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = '_Pooling3D' + + const { pool_size = [2, 2, 2], strides = null, padding = 'valid', data_format = 'channels_last' } = attrs + + if (Array.isArray(pool_size)) { + this.poolSize = pool_size + } else { + this.poolSize = [pool_size, pool_size, pool_size] + } + + if (Array.isArray(strides)) { + this.strides = strides + } else if (strides !== null) { + this.strides = [strides, strides, strides] + } else { + this.strides = this.poolSize + } + + this.padding = padding + this.dataFormat = data_format + + // default pooling function + // can be `max` or `average` + this.poolingFunc = 'max' + + // GPU setup + if (this.gpu) { + this.poolingProgram = webgl2.compileProgram(poolingProgramSource) + this.poolingFragmentsProgram = webgl2.compileProgram(poolingFragmentsProgramSource) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * Method for computing output dimensions and padding, based on input dimensions, kernel size, and padding mode. + * + * For tensorflow implementation of padding, see: + * https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/framework/common_shape_fns.cc + * + * @param {number[]} inputShape + */ + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return + } + + const [inputDim1, inputDim2, inputDim3, inputChannels] = inputShape + const [poolDim1, poolDim2, poolDim3] = this.poolSize + + const outputDim1 = + this.padding === 'same' + ? Math.floor((inputDim1 + this.strides[0] - 1) / this.strides[0]) + : Math.floor((inputDim1 - poolDim1 + this.strides[0]) / this.strides[0]) + const outputDim2 = + this.padding === 'same' + ? Math.floor((inputDim2 + this.strides[1] - 1) / this.strides[1]) + : Math.floor((inputDim2 - poolDim2 + this.strides[1]) / this.strides[1]) + const outputDim3 = + this.padding === 'same' + ? Math.floor((inputDim3 + this.strides[2] - 1) / this.strides[2]) + : Math.floor((inputDim3 - poolDim3 + this.strides[2]) / this.strides[2]) + + const paddingDim1 = + this.padding === 'same' ? Math.max(0, Math.floor((outputDim1 - 1) * this.strides[0] + poolDim1 - inputDim1)) : 0 + const paddingDim2 = + this.padding === 'same' ? Math.max(0, Math.floor((outputDim2 - 1) * this.strides[1] + poolDim2 - inputDim2)) : 0 + const paddingDim3 = + this.padding === 'same' ? Math.max(0, Math.floor((outputDim3 - 1) * this.strides[2] + poolDim3 - inputDim3)) : 0 + const paddingDim1Before = Math.floor(paddingDim1 / 2) + const paddingDim1After = paddingDim1 - paddingDim1Before + const paddingDim2Before = Math.floor(paddingDim2 / 2) + const paddingDim2After = paddingDim2 - paddingDim2Before + const paddingDim3Before = Math.floor(paddingDim3 / 2) + const paddingDim3After = paddingDim3 - paddingDim3Before + + this.outputShape = [outputDim1, outputDim2, outputDim3, inputChannels] + this.inputPadding = [ + paddingDim1Before, + paddingDim1After, + paddingDim2Before, + paddingDim2After, + paddingDim3Before, + paddingDim3After + ] + } + + /** + * Pad input tensor if necessary, for padding='same'. See above for notes on calculating padding. + * + * For max, we pad with -infinity. + * + * For average we pad with zero. + * + * @param {Tensor} x + * @returns {Tensor} + */ + _padInput(x) { + if (this.padding === 'same') { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape + const [ + paddingDim1Before, + paddingDim1After, + paddingDim2Before, + paddingDim2After, + paddingDim3Before, + paddingDim3After + ] = this.inputPadding + const newDim1 = inputDim1 + paddingDim1Before + paddingDim1After + const newDim2 = inputDim2 + paddingDim2Before + paddingDim2After + const newDim3 = inputDim3 + paddingDim3Before + paddingDim3After + + const _x = new Tensor([], [newDim1, newDim2, newDim3, inputChannels]) + if (this.poolingFunc === 'max') { + ops.assigns(_x.tensor, Number.NEGATIVE_INFINITY) + } + + ops.assign( + _x.tensor + .hi( + inputDim1 + paddingDim1Before, + inputDim2 + paddingDim2Before, + inputDim3 + paddingDim3Before, + inputChannels + ) + .lo(paddingDim1Before, paddingDim2Before, paddingDim3Before, 0), + x.tensor + ) + return _x + } + return x + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + // convert to channels_last ordering + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0) + } + + this._calcOutputShape(x.tensor.shape) + x = this._padInput(x) + + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape + const [poolDim1, poolDim2, poolDim3] = this.poolSize + this.output = new Tensor([], this.outputShape) + let patch = new Tensor([], [poolDim1, poolDim2, poolDim3, inputChannels]) + + // keep track of padding since these values are not included in pooling + // for max, we can ignore since padding values are set to -infinity + const [ + paddingDim1Before, + paddingDim1After, + paddingDim2Before, + paddingDim2After, + paddingDim3Before, + paddingDim3After + ] = this.inputPadding + + for (let i = 0, _i = 0; i <= inputDim1 - poolDim1; i += this.strides[0], _i++) { + let dim1InPadding = 0 + if (i < paddingDim1Before) { + dim1InPadding = paddingDim1Before - i + } else if (i + poolDim1 > inputDim1 - paddingDim1After) { + dim1InPadding = i + poolDim1 - (inputDim1 - paddingDim1After) + } + + for (let j = 0, _j = 0; j <= inputDim2 - poolDim2; j += this.strides[1], _j++) { + let dim2InPadding = 0 + if (j < paddingDim2Before) { + dim2InPadding = paddingDim2Before - j + } else if (j + poolDim2 > inputDim2 - paddingDim2After) { + dim2InPadding = j + poolDim2 - (inputDim2 - paddingDim2After) + } + + for (let k = 0, _k = 0; k <= inputDim3 - poolDim3; k += this.strides[2], _k++) { + let dim3InPadding = 0 + if (k < paddingDim3Before) { + dim3InPadding = paddingDim3Before - k + } else if (k + poolDim3 > inputDim3 - paddingDim3After) { + dim3InPadding = k + poolDim3 - (inputDim3 - paddingDim3After) + } + const nbCellsEffective = (poolDim1 - dim1InPadding) * (poolDim2 - dim2InPadding) * (poolDim3 - dim3InPadding) + + ops.assign(patch.tensor, x.tensor.hi(i + poolDim1, j + poolDim2, k + poolDim3, inputChannels).lo(i, j, k, 0)) + for (let c = 0; c < inputChannels; c++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(_i, _j, _k, c, ops.sup(patch.tensor.pick(null, null, null, c))) + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(_i, _j, _k, c, ops.sum(patch.tensor.pick(null, null, null, c)) / nbCellsEffective) + } + } + } + } + } + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2) + } + } + + /** + * Convert input tensor to column matrix + * + * @param {Tensor} x + * @returns {Tensor} + */ + _vol2col(x) { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape + if (!this.tiledInput) { + this.tiledInput = new Tensor([], [inputDim1 * inputDim2 * inputDim3, inputChannels]) + } + + const patch = new Tensor([], [inputDim1, inputDim2, inputDim3]) + const patchRaveled = new Tensor([], [inputDim1 * inputDim2 * inputDim3]) + for (let c = 0; c < inputChannels; c++) { + ops.assign(patch.tensor, x.tensor.pick(null, null, null, c)) + patchRaveled.replaceTensorData(patch.tensor.data) + ops.assign(this.tiledInput.tensor.pick(null, c), patchRaveled.tensor) + } + + return this.tiledInput + } + + /** + * Pre-compute index map for GPU pooling function + */ + _createIndexMap() { + if (this.poolIndexMap) { + return + } + + let inputDim1 = this.inputShape[0] + let inputDim2 = this.inputShape[1] + let inputDim3 = this.inputShape[2] + const rowIndices = new Tensor([], [inputDim1, inputDim2, inputDim3]) + let index = 0 + for (let i = 0; i < inputDim1; i++) { + for (let j = 0; j < inputDim2; j++) { + for (let k = 0; k < inputDim3; k++) { + rowIndices.tensor.set(i, j, k, index) + index += 1 + } + } + } + + // padding for border mode 'same' + if (this.padding === 'same') { + const [ + paddingDim1Before, + paddingDim1After, + paddingDim2Before, + paddingDim2After, + paddingDim3Before, + paddingDim3After + ] = this.inputPadding + inputDim1 = inputDim1 + paddingDim1Before + paddingDim1After + inputDim2 = inputDim2 + paddingDim2Before + paddingDim2After + inputDim3 = inputDim3 + paddingDim3Before + paddingDim3After + const _rowIndices = new Tensor([], [inputDim1, inputDim2, inputDim3]) + ops.assigns(_rowIndices.tensor, -1) + ops.assign( + _rowIndices.tensor + .hi( + this.inputShape[0] + paddingDim1Before, + this.inputShape[1] + paddingDim2Before, + this.inputShape[2] + paddingDim3Before + ) + .lo(paddingDim1Before, paddingDim2Before, paddingDim3Before), + rowIndices.tensor + ) + rowIndices.tensor = _rowIndices.tensor + } + + const [poolDim1, poolDim2, poolDim3] = this.poolSize + const outputDim1 = this.outputShape[0] + const outputDim2 = this.outputShape[1] + const outputDim3 = this.outputShape[2] + + this.poolIndexMap = new Tensor([], [outputDim1 * outputDim2 * outputDim3, poolDim1 * poolDim2 * poolDim3], { + type: Int32Array + }) + + const patchRow = new Tensor([], [poolDim1, poolDim2, poolDim3]) + let offset = 0 + for (let i = 0, limit = inputDim1 - poolDim1; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - poolDim2; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - poolDim3; k <= limit; k += this.strides[2]) { + ops.assign(patchRow.tensor, rowIndices.tensor.hi(i + poolDim1, j + poolDim2, k + poolDim3).lo(i, j, k)) + this.poolIndexMap.tensor.data.set(patchRow.tensor.data, offset) + offset += poolDim1 * poolDim2 * poolDim3 + } + } + } + + this.poolIndexMap.createGLTexture({ type: '2d', format: 'int', supportsTextureFragments: true }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + // convert to channels_last ordering + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0) + } + this.inputShape = x.tensor.shape + this._vol2col(x) + this.tiledInput.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + } + this._calcOutputShape(this.inputShape) + this._createIndexMap() + + // create output textures if doesn't already exist + if (!this.output) { + const [outputDim1, outputDim2, outputDim3, inputChannels] = this.outputShape + const outputTextureShape = [outputDim1 * outputDim2 * outputDim3, inputChannels] + this.output = new Tensor([], outputTextureShape) + this.output.createGLTexture({ type: '2d', format: 'float', supportsTextureFragments: true }) + this.output.is2DReshaped = true + this.output.originalShape = this.outputShape + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1) + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.tiledInput + const poolSize = this.poolSize[0] * this.poolSize[1] * this.poolSize[2] + // `true` if max pooling, `false` if average pooling + const isMaxPooling = this.poolingFunc === 'max' + + const programUniforms = [ + { value: this.output.glTextureShape[1], type: 'int', name: 'channels' }, + { value: poolSize, type: 'int', name: 'poolSize' }, + { value: +isMaxPooling, type: 'bool', name: 'isMaxPooling' } + ] + if (input.glTextureFragments) { + input.convert2DRowFragmentedGLTextureToColStack() + webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ input: input, name: 'x' }, { input: this.poolIndexMap, name: 'poolIndexMap' }], + uniforms: programUniforms, + supportsTextureFragments: true + }) + input.removeGLTextureFragmentsAsColStack() + } else { + webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ input: input, name: 'x' }, { input: this.poolIndexMap, name: 'poolIndexMap' }], + uniforms: programUniforms + }) + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + this.output.reshapeFrom2D() + + // convert back to channels_first ordering if necessary + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2) + } + } + } +} diff --git a/keras-js/src/layers/pooling/index.js b/keras-js/src/layers/pooling/index.js new file mode 100644 index 0000000000..1eaa28fdd5 --- /dev/null +++ b/keras-js/src/layers/pooling/index.js @@ -0,0 +1,27 @@ +import MaxPooling1D from './MaxPooling1D' +import MaxPooling2D from './MaxPooling2D' +import MaxPooling3D from './MaxPooling3D' +import AveragePooling1D from './AveragePooling1D' +import AveragePooling2D from './AveragePooling2D' +import AveragePooling3D from './AveragePooling3D' +import GlobalMaxPooling1D from './GlobalMaxPooling1D' +import GlobalMaxPooling2D from './GlobalMaxPooling2D' +import GlobalMaxPooling3D from './GlobalMaxPooling3D' +import GlobalAveragePooling1D from './GlobalAveragePooling1D' +import GlobalAveragePooling2D from './GlobalAveragePooling2D' +import GlobalAveragePooling3D from './GlobalAveragePooling3D' + +export { + MaxPooling1D, + MaxPooling2D, + MaxPooling3D, + AveragePooling1D, + AveragePooling2D, + AveragePooling3D, + GlobalMaxPooling1D, + GlobalMaxPooling2D, + GlobalMaxPooling3D, + GlobalAveragePooling1D, + GlobalAveragePooling2D, + GlobalAveragePooling3D +} diff --git a/keras-js/src/layers/recurrent/GRU.js b/keras-js/src/layers/recurrent/GRU.js new file mode 100644 index 0000000000..19646d585f --- /dev/null +++ b/keras-js/src/layers/recurrent/GRU.js @@ -0,0 +1,520 @@ +import * as activations from '../../activations' +import Tensor from '../../Tensor' +import Layer from '../../Layer' +import { webgl2 } from '../../WebGL2' +import { gemv } from 'ndarray-blas-level2' +import ops from 'ndarray-ops' +import cwise from 'cwise' +import copyTextureProgramSource from '../../webgl/copyTexture.glsl' +import matMulProgramSource from '../../webgl/matMul.glsl' +import * as activationProgramSources from '../../activations/programSources' +import gateSummationProgramSource from './gateSummation.glsl' +import gateProductProgramSource from './gateProduct.glsl' +import timestepReadProgramSource from './timestepRead.glsl' +import timestepWriteProgramSource from './timestepWrite.glsl' +import updateProgramSource from './GRU.update.glsl' + +/** + * GRU layer class + */ +export default class GRU extends Layer { + /** + * Creates a GRU layer + * + * @param {Object} [attrs] - layer attributes + * @param {number} [attrs.units] - output dimensionality + * @param {number} [attrs.activation] - activation function + * @param {number} [attrs.recurrent_activation] - inner activation function + * @param {number} [attrs.use_bias] - use bias + * @param {number} [attrs.return_sequences] - return the last output in the output sequence or the full sequence + * @param {number} [attrs.go_backwards] - process the input sequence backwards + * @param {number} [attrs.stateful] - whether to save the last state as the initial state for the next pass + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'GRU' + + const { + units = 1, + activation = 'tanh', + use_bias = true, + recurrent_activation = 'hard_sigmoid', + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs + + this.units = units + + // keep this.activation and this.recurrentActivation for Bidirectional wrapper layer to use + this.activation = activation + this.recurrentActivation = recurrent_activation + this.activationFunc = activations[activation] + this.recurrentActivationFunc = activations[recurrent_activation] + + this.use_bias = use_bias + + this.returnSequences = return_sequences + this.goBackwards = go_backwards + this.stateful = stateful + + // Layer weights specification + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel'] + + // GPU setup + if (this.gpu) { + this.copyTextureProgram = webgl2.compileProgram(copyTextureProgramSource) + this.matMulProgram = webgl2.compileProgram(matMulProgramSource) + this.activationProgram = webgl2.compileProgram(activationProgramSources[this.activation]) + this.recurrentActivationProgram = webgl2.compileProgram(activationProgramSources[this.recurrentActivation]) + this.gateSummationProgram = webgl2.compileProgram(gateSummationProgramSource) + this.gateProductProgram = webgl2.compileProgram(gateProductProgramSource) + this.timestepReadProgram = webgl2.compileProgram(timestepReadProgramSource) + this.timestepWriteProgram = webgl2.compileProgram(timestepWriteProgramSource) + this.updateProgram = webgl2.compileProgram(updateProgramSource) + } + } + + /** + * Method for setting layer weights. Extends `super` method. + * + * W weight tensor is split into W_z, W_r, W_h + * + * U weight tensor is split into U_z, U_r, U_h + * + * b weight tensor is split into b_z, b_r, b_h (or create empty bias if this.use_bias is false) + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + super.setWeights(weightsArr) + + const shape_W = this.weights['kernel'].tensor.shape + this.weights['W_z'] = new Tensor([], [shape_W[0], this.units]) + this.weights['W_r'] = new Tensor([], [shape_W[0], this.units]) + this.weights['W_h'] = new Tensor([], [shape_W[0], this.units]) + ops.assign(this.weights['W_z'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], this.units).lo(0, 0)) + ops.assign( + this.weights['W_r'].tensor, + this.weights['kernel'].tensor.hi(shape_W[0], 2 * this.units).lo(0, this.units) + ) + ops.assign( + this.weights['W_h'].tensor, + this.weights['kernel'].tensor.hi(shape_W[0], 3 * this.units).lo(0, 2 * this.units) + ) + + const shape_U = this.weights['recurrent_kernel'].tensor.shape + this.weights['U_z'] = new Tensor([], [shape_U[0], this.units]) + this.weights['U_r'] = new Tensor([], [shape_U[0], this.units]) + this.weights['U_h'] = new Tensor([], [shape_U[0], this.units]) + ops.assign(this.weights['U_z'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], this.units).lo(0, 0)) + ops.assign( + this.weights['U_r'].tensor, + this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 2 * this.units).lo(0, this.units) + ) + ops.assign( + this.weights['U_h'].tensor, + this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 3 * this.units).lo(0, 2 * this.units) + ) + + this.weights['b_z'] = new Tensor([], [this.units]) + this.weights['b_r'] = new Tensor([], [this.units]) + this.weights['b_h'] = new Tensor([], [this.units]) + if (this.use_bias) { + ops.assign(this.weights['b_z'].tensor, this.weights['bias'].tensor.hi(this.units).lo(0)) + ops.assign(this.weights['b_r'].tensor, this.weights['bias'].tensor.hi(2 * this.units).lo(this.units)) + ops.assign(this.weights['b_h'].tensor, this.weights['bias'].tensor.hi(3 * this.units).lo(2 * this.units)) + } + + if (this.gpu) { + const names = ['W_z', 'W_r', 'W_h', 'U_z', 'U_r', 'U_h', 'b_z', 'b_r', 'b_h'] + names.forEach(name => { + this.weights[name].createGLTexture({ type: '2d', format: 'float' }) + }) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + _combine = cwise({ + args: ['array', 'array', 'array', 'array'], + body: function(_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b + } + }) + + _update = cwise({ + args: ['array', 'array', 'array'], + body: function(_h, _htm1, _z) { + _h = _h * (1 - _z) + _htm1 * _z + } + }) + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + const dimUpdateGate = this.weights['b_z'].tensor.shape[0] + const dimResetGate = this.weights['b_r'].tensor.shape[0] + const dimHiddenState = this.weights['b_h'].tensor.shape[0] + + const currentUpdateGateState = new Tensor([], [dimUpdateGate]) + const tempXZ = new Tensor([], [dimUpdateGate]) + const tempHZ = new Tensor([], [dimUpdateGate]) + + const currentResetGateState = new Tensor([], [dimResetGate]) + const tempXR = new Tensor([], [dimResetGate]) + const tempHR = new Tensor([], [dimResetGate]) + + const currentHiddenState = + this.stateful && this.currentHiddenState ? this.currentHiddenState : new Tensor([], [dimHiddenState]) + const tempXH = new Tensor([], [dimHiddenState]) + const tempHH = new Tensor([], [dimHiddenState]) + const previousHiddenState = new Tensor([], [dimHiddenState]) + + this.hiddenStateSequence = new Tensor([], [x.tensor.shape[0], dimHiddenState]) + + const currentX = new Tensor([], [x.tensor.shape[1]]) + + const _step = () => { + ops.assign(previousHiddenState.tensor, currentHiddenState.tensor) + + gemv(1, this.weights['W_z'].tensor.transpose(1, 0), currentX.tensor, 1, tempXZ.tensor) + gemv(1, this.weights['U_z'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHZ.tensor) + this._combine(currentUpdateGateState.tensor, tempXZ.tensor, tempHZ.tensor, this.weights['b_z'].tensor) + this.recurrentActivationFunc(currentUpdateGateState) + + gemv(1, this.weights['W_r'].tensor.transpose(1, 0), currentX.tensor, 1, tempXR.tensor) + gemv(1, this.weights['U_r'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHR.tensor) + this._combine(currentResetGateState.tensor, tempXR.tensor, tempHR.tensor, this.weights['b_r'].tensor) + this.recurrentActivationFunc(currentResetGateState) + + ops.muleq(currentResetGateState.tensor, previousHiddenState.tensor) + gemv(1, this.weights['W_h'].tensor.transpose(1, 0), currentX.tensor, 1, tempXH.tensor) + gemv(1, this.weights['U_h'].tensor.transpose(1, 0), currentResetGateState.tensor, 1, tempHH.tensor) + this._combine(currentHiddenState.tensor, tempXH.tensor, tempHH.tensor, this.weights['b_h'].tensor) + this.activationFunc(currentHiddenState) + + this._update(currentHiddenState.tensor, previousHiddenState.tensor, currentUpdateGateState.tensor) + } + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i + ops.assign(currentX.tensor, x.tensor.pick(inputIndex, null)) + + // clear temp tensors + const tempTensors = [tempXZ, tempHZ, tempXR, tempHR, tempXH, tempHH] + tempTensors.forEach(temp => ops.assigns(temp.tensor, 0)) + + // advance timestep + _step() + + if (this.returnSequences) { + ops.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor) + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence + } else { + this.output = currentHiddenState + } + + if (this.stateful) { + this.currentHiddenState = currentHiddenState + } + } + + /** + * Advance time step in _callGPU + */ + _stepGPU() { + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ input: this.currentHiddenState, name: 'source' }] + }) + + // update gate + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXZ, + inputs: [{ input: this.currentX, name: 'A' }, { input: this.weights['W_z'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHZ, + inputs: [{ input: this.previousHiddenState, name: 'A' }, { input: this.weights['U_z'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentUpdateGateStatePreactiv, + inputs: [ + { input: this.tempXZ, name: 't1' }, + { input: this.tempHZ, name: 't2' }, + { input: this.weights['b_z'], name: 'bias' } + ] + }) + + if (this.recurrentActivation !== 'linear') { + webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentUpdateGateState, + inputs: [{ input: this.currentUpdateGateStatePreactiv, name: 'x' }] + }) + } else { + this.currentUpdateGateState = this.currentUpdateGateStatePreactiv + } + + // reset gate + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXR, + inputs: [{ input: this.currentX, name: 'A' }, { input: this.weights['W_r'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHR, + inputs: [{ input: this.previousHiddenState, name: 'A' }, { input: this.weights['U_r'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentResetGateStatePreactiv, + inputs: [ + { input: this.tempXR, name: 't1' }, + { input: this.tempHR, name: 't2' }, + { input: this.weights['b_r'], name: 'bias' } + ] + }) + + if (this.recurrentActivation !== 'linear') { + webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentResetGateState, + inputs: [{ input: this.currentResetGateStatePreactiv, name: 'x' }] + }) + } else { + this.currentResetGateState = this.currentResetGateStatePreactiv + } + + // hidden state + + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentResetGateStateCopy, + inputs: [{ input: this.currentResetGateState, name: 'source' }] + }) + + webgl2.runProgram({ + program: this.gateProductProgram, + output: this.currentResetGateState, + inputs: [{ input: this.currentResetGateStateCopy, name: 't1' }, { input: this.previousHiddenState, name: 't2' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXH, + inputs: [{ input: this.currentX, name: 'A' }, { input: this.weights['W_h'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHH, + inputs: [{ input: this.currentResetGateState, name: 'A' }, { input: this.weights['U_h'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentHiddenStatePreactiv, + inputs: [ + { input: this.tempXH, name: 't1' }, + { input: this.tempHH, name: 't2' }, + { input: this.weights['b_h'], name: 'bias' } + ] + }) + + if (this.activation !== 'linear') { + webgl2.runProgram({ + program: this.activationProgram, + output: this.currentHiddenState, + inputs: [{ input: this.currentHiddenStatePreactiv, name: 'x' }] + }) + } else { + this.currentHiddenState = this.currentHiddenStatePreactiv + } + + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentHiddenStateCopy, + inputs: [{ input: this.currentHiddenState, name: 'source' }] + }) + + webgl2.runProgram({ + program: this.updateProgram, + output: this.currentHiddenState, + inputs: [ + { input: this.currentHiddenStateCopy, name: 'h' }, + { input: this.previousHiddenState, name: 'htm1' }, + { input: this.currentUpdateGateState, name: 'z' } + ] + }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + const dimUpdateGate = this.weights['b_z'].glTextureShape[1] + const dimResetGate = this.weights['b_r'].glTextureShape[1] + const dimHiddenState = this.weights['b_h'].glTextureShape[1] + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new Tensor([], [dimHiddenState]) + this.currentHiddenState.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentHiddenStateCopy) { + this.currentHiddenStateCopy = new Tensor([], [dimHiddenState]) + this.currentHiddenStateCopy.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentHiddenStatePreactiv) { + this.currentHiddenStatePreactiv = new Tensor([], [dimHiddenState]) + this.currentHiddenStatePreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentUpdateGateState) { + this.currentUpdateGateState = new Tensor([], [dimUpdateGate]) + this.currentUpdateGateState.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentUpdateGateStatePreactiv) { + this.currentUpdateGateStatePreactiv = new Tensor([], [dimUpdateGate]) + this.currentUpdateGateStatePreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempXZ) { + this.tempXZ = new Tensor([], [dimUpdateGate]) + this.tempXZ.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempHZ) { + this.tempHZ = new Tensor([], [dimUpdateGate]) + this.tempHZ.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentResetGateState) { + this.currentResetGateState = new Tensor([], [dimResetGate]) + this.currentResetGateState.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentResetGateStateCopy) { + this.currentResetGateStateCopy = new Tensor([], [dimResetGate]) + this.currentResetGateStateCopy.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentResetGateStatePreactiv) { + this.currentResetGateStatePreactiv = new Tensor([], [dimResetGate]) + this.currentResetGateStatePreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempXR) { + this.tempXR = new Tensor([], [dimResetGate]) + this.tempXR.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempHR) { + this.tempHR = new Tensor([], [dimResetGate]) + this.tempHR.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.tempXH) { + this.tempXH = new Tensor([], [dimHiddenState]) + this.tempXH.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempHH) { + this.tempHH = new Tensor([], [dimHiddenState]) + this.tempHH.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.previousHiddenState) { + this.previousHiddenState = new Tensor([], [dimHiddenState]) + this.previousHiddenState.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new Tensor([], [x.glTextureShape[0], dimHiddenState]) + this.hiddenStateSequence.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new Tensor([], [x.glTextureShape[0], dimHiddenState]) + this.hiddenStateSequenceCopy.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentX) { + this.currentX = new Tensor([], [x.glTextureShape[1]]) + this.currentX.createGLTexture({ type: '2d', format: 'float' }) + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i + + webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ input: x, name: 'x' }], + uniforms: [{ value: inputIndex, type: 'int', name: 'index' }] + }) + + this._stepGPU() + + if (this.returnSequences) { + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ input: this.hiddenStateSequence, name: 'source' }] + }) + webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ input: this.currentHiddenState, name: 'x' }, { input: this.hiddenStateSequenceCopy, name: 'y' }], + uniforms: [{ value: i, type: 'int', name: 'index' }] + }) + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence + } else { + this.output = this.currentHiddenState + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/recurrent/GRU.update.glsl b/keras-js/src/layers/recurrent/GRU.update.glsl new file mode 100644 index 0000000000..f9deb13807 --- /dev/null +++ b/keras-js/src/layers/recurrent/GRU.update.glsl @@ -0,0 +1,20 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D h; +uniform sampler2D htm1; +uniform sampler2D z; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(h, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + float h_val = texelFetch(h, ivec2(out_x, out_y), 0).r; + float htm1_val = texelFetch(htm1, ivec2(out_x, out_y), 0).r; + float z_val = texelFetch(z, ivec2(out_x, out_y), 0).r; + + outColor = vec4(h_val * (float(1.0) - z_val) + htm1_val * z_val); +} diff --git a/keras-js/src/layers/recurrent/LSTM.js b/keras-js/src/layers/recurrent/LSTM.js new file mode 100644 index 0000000000..2188de64e6 --- /dev/null +++ b/keras-js/src/layers/recurrent/LSTM.js @@ -0,0 +1,629 @@ +import * as activations from '../../activations' +import Tensor from '../../Tensor' +import Layer from '../../Layer' +import { webgl2 } from '../../WebGL2' +import { gemv } from 'ndarray-blas-level2' +import ops from 'ndarray-ops' +import cwise from 'cwise' +import copyTextureProgramSource from '../../webgl/copyTexture.glsl' +import matMulProgramSource from '../../webgl/matMul.glsl' +import * as activationProgramSources from '../../activations/programSources' +import gateSummationProgramSource from './gateSummation.glsl' +import gateProductProgramSource from './gateProduct.glsl' +import timestepReadProgramSource from './timestepRead.glsl' +import timestepWriteProgramSource from './timestepWrite.glsl' +import updateProgramSource from './LSTM.update.glsl' + +/** + * LSTM layer class + */ +export default class LSTM extends Layer { + /** + * Creates a LSTM layer + * + * @param {Object} [attrs] - layer attributes + * @param {number} [attrs.units] - output dimensionality + * @param {number} [attrs.activation] - activation function + * @param {number} [attrs.recurrent_activation] - inner activation function + * @param {number} [attrs.use_bias] - use bias + * @param {number} [attrs.return_sequences] - return the last output in the output sequence or the full sequence + * @param {number} [attrs.go_backwards] - process the input sequence backwards + * @param {number} [attrs.stateful] - whether to save the last state as the initial state for the next pass + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'LSTM' + + const { + units = 1, + activation = 'tanh', + use_bias = true, + recurrent_activation = 'hard_sigmoid', + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs + + this.units = units + + // keep this.activation and this.recurrentActivation for Bidirectional wrapper layer to use + this.activation = activation + this.recurrentActivation = recurrent_activation + this.activationFunc = activations[activation] + this.recurrentActivationFunc = activations[recurrent_activation] + + this.use_bias = use_bias + + this.returnSequences = return_sequences + this.goBackwards = go_backwards + this.stateful = stateful + + // Layer weights specification + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel'] + + // GPU setup + if (this.gpu) { + this.copyTextureProgram = webgl2.compileProgram(copyTextureProgramSource) + this.matMulProgram = webgl2.compileProgram(matMulProgramSource) + this.activationProgram = webgl2.compileProgram(activationProgramSources[this.activation]) + this.recurrentActivationProgram = webgl2.compileProgram(activationProgramSources[this.recurrentActivation]) + this.gateSummationProgram = webgl2.compileProgram(gateSummationProgramSource) + this.gateProductProgram = webgl2.compileProgram(gateProductProgramSource) + this.timestepReadProgram = webgl2.compileProgram(timestepReadProgramSource) + this.timestepWriteProgram = webgl2.compileProgram(timestepWriteProgramSource) + this.updateProgram = webgl2.compileProgram(updateProgramSource) + } + } + + /** + * Method for setting layer weights. Extends `super` method. + * + * W weight tensor is split into W_i, W_f, W_c, W_o + * + * U weight tensor is split into U_i, U_f, U_c, U_o + * + * b weight tensor is split into b_i, b_f, b_c, b_o (or create empty bias if this.use_bias is false) + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + super.setWeights(weightsArr) + + const shape_W = this.weights['kernel'].tensor.shape + this.weights['W_i'] = new Tensor([], [shape_W[0], this.units]) + this.weights['W_f'] = new Tensor([], [shape_W[0], this.units]) + this.weights['W_c'] = new Tensor([], [shape_W[0], this.units]) + this.weights['W_o'] = new Tensor([], [shape_W[0], this.units]) + ops.assign(this.weights['W_i'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], this.units).lo(0, 0)) + ops.assign( + this.weights['W_f'].tensor, + this.weights['kernel'].tensor.hi(shape_W[0], 2 * this.units).lo(0, this.units) + ) + ops.assign( + this.weights['W_c'].tensor, + this.weights['kernel'].tensor.hi(shape_W[0], 3 * this.units).lo(0, 2 * this.units) + ) + ops.assign( + this.weights['W_o'].tensor, + this.weights['kernel'].tensor.hi(shape_W[0], 4 * this.units).lo(0, 3 * this.units) + ) + + const shape_U = this.weights['recurrent_kernel'].tensor.shape + this.weights['U_i'] = new Tensor([], [shape_U[0], this.units]) + this.weights['U_f'] = new Tensor([], [shape_U[0], this.units]) + this.weights['U_c'] = new Tensor([], [shape_U[0], this.units]) + this.weights['U_o'] = new Tensor([], [shape_U[0], this.units]) + ops.assign(this.weights['U_i'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], this.units).lo(0, 0)) + ops.assign( + this.weights['U_f'].tensor, + this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 2 * this.units).lo(0, this.units) + ) + ops.assign( + this.weights['U_c'].tensor, + this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 3 * this.units).lo(0, 2 * this.units) + ) + ops.assign( + this.weights['U_o'].tensor, + this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 4 * this.units).lo(0, 3 * this.units) + ) + + this.weights['b_i'] = new Tensor([], [this.units]) + this.weights['b_f'] = new Tensor([], [this.units]) + this.weights['b_c'] = new Tensor([], [this.units]) + this.weights['b_o'] = new Tensor([], [this.units]) + if (this.use_bias) { + ops.assign(this.weights['b_i'].tensor, this.weights['bias'].tensor.hi(this.units).lo(0)) + ops.assign(this.weights['b_f'].tensor, this.weights['bias'].tensor.hi(2 * this.units).lo(this.units)) + ops.assign(this.weights['b_c'].tensor, this.weights['bias'].tensor.hi(3 * this.units).lo(2 * this.units)) + ops.assign(this.weights['b_o'].tensor, this.weights['bias'].tensor.hi(4 * this.units).lo(3 * this.units)) + } + + if (this.gpu) { + const names = ['W_i', 'W_f', 'W_c', 'W_o', 'U_i', 'U_f', 'U_c', 'U_o', 'b_i', 'b_f', 'b_c', 'b_o'] + names.forEach(name => { + this.weights[name].createGLTexture({ type: '2d', format: 'float' }) + }) + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + _combine = cwise({ + args: ['array', 'array', 'array', 'array'], + body: function(_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b + } + }) + + _update = cwise({ + args: ['array', 'array', 'array', 'array'], + body: function(_c, _ctm1, _i, _f) { + _c = _c * _i + _ctm1 * _f + } + }) + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + const dimInputGate = this.weights['b_i'].tensor.shape[0] + const dimCandidate = this.weights['b_c'].tensor.shape[0] + const dimForgetGate = this.weights['b_f'].tensor.shape[0] + const dimOutputGate = this.weights['b_o'].tensor.shape[0] + + const currentInputGateState = new Tensor([], [dimInputGate]) + const tempXI = new Tensor([], [dimInputGate]) + const tempHI = new Tensor([], [dimInputGate]) + + const currentForgetGateState = new Tensor([], [dimForgetGate]) + const tempXF = new Tensor([], [dimForgetGate]) + const tempHF = new Tensor([], [dimForgetGate]) + + const currentOutputGateState = new Tensor([], [dimOutputGate]) + const tempXO = new Tensor([], [dimOutputGate]) + const tempHO = new Tensor([], [dimOutputGate]) + + const currentCandidate = new Tensor([], [dimCandidate]) + const tempXC = new Tensor([], [dimCandidate]) + const tempHC = new Tensor([], [dimCandidate]) + const previousCandidate = + this.stateful && this.previousCandidate ? this.previousCandidate : new Tensor([], [dimCandidate]) + + const currentHiddenState = + this.stateful && this.currentHiddenState ? this.currentHiddenState : new Tensor([], [dimCandidate]) + const previousHiddenState = new Tensor([], [dimCandidate]) + + this.hiddenStateSequence = new Tensor([], [x.tensor.shape[0], dimCandidate]) + + const currentX = new Tensor([], [x.tensor.shape[1]]) + + const _step = () => { + ops.assign(previousHiddenState.tensor, currentHiddenState.tensor) + + gemv(1, this.weights['W_i'].tensor.transpose(1, 0), currentX.tensor, 1, tempXI.tensor) + gemv(1, this.weights['U_i'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHI.tensor) + this._combine(currentInputGateState.tensor, tempXI.tensor, tempHI.tensor, this.weights['b_i'].tensor) + this.recurrentActivationFunc(currentInputGateState) + + gemv(1, this.weights['W_f'].tensor.transpose(1, 0), currentX.tensor, 1, tempXF.tensor) + gemv(1, this.weights['U_f'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHF.tensor) + this._combine(currentForgetGateState.tensor, tempXF.tensor, tempHF.tensor, this.weights['b_f'].tensor) + this.recurrentActivationFunc(currentForgetGateState) + + gemv(1, this.weights['W_o'].tensor.transpose(1, 0), currentX.tensor, 1, tempXO.tensor) + gemv(1, this.weights['U_o'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHO.tensor) + this._combine(currentOutputGateState.tensor, tempXO.tensor, tempHO.tensor, this.weights['b_o'].tensor) + this.recurrentActivationFunc(currentOutputGateState) + + gemv(1, this.weights['W_c'].tensor.transpose(1, 0), currentX.tensor, 1, tempXC.tensor) + gemv(1, this.weights['U_c'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHC.tensor) + this._combine(currentCandidate.tensor, tempXC.tensor, tempHC.tensor, this.weights['b_c'].tensor) + this.activationFunc(currentCandidate) + + this._update( + currentCandidate.tensor, + previousCandidate.tensor, + currentInputGateState.tensor, + currentForgetGateState.tensor + ) + + ops.assign(previousCandidate.tensor, currentCandidate.tensor) + + this.activationFunc(currentCandidate) + ops.mul(currentHiddenState.tensor, currentOutputGateState.tensor, currentCandidate.tensor) + } + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i + ops.assign(currentX.tensor, x.tensor.pick(inputIndex, null)) + + // clear temp tensors + const tempTensors = [tempXI, tempHI, tempXF, tempHF, tempXO, tempHO, tempXC, tempHC] + tempTensors.forEach(temp => ops.assigns(temp.tensor, 0)) + + // advance timestep + _step() + + ops.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor) + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence + } else { + this.output = currentHiddenState + } + + if (this.stateful) { + this.previousCandidate = previousCandidate + this.currentHiddenState = currentHiddenState + } + } + + /** + * Advance time step in _callGPU + */ + _stepGPU() { + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ input: this.currentHiddenState, name: 'source' }] + }) + + // input gate + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXI, + inputs: [{ input: this.currentX, name: 'A' }, { input: this.weights['W_i'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHI, + inputs: [{ input: this.previousHiddenState, name: 'A' }, { input: this.weights['U_i'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentInputGateStatePreactiv, + inputs: [ + { input: this.tempXI, name: 't1' }, + { input: this.tempHI, name: 't2' }, + { input: this.weights['b_i'], name: 'bias' } + ] + }) + + if (this.recurrentActivation !== 'linear') { + webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentInputGateState, + inputs: [{ input: this.currentInputGateStatePreactiv, name: 'x' }] + }) + } else { + this.currentInputGateState = this.currentInputGateStatePreactiv + } + + // forget gate + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXF, + inputs: [{ input: this.currentX, name: 'A' }, { input: this.weights['W_f'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHF, + inputs: [{ input: this.previousHiddenState, name: 'A' }, { input: this.weights['U_f'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentForgetGateStatePreactiv, + inputs: [ + { input: this.tempXF, name: 't1' }, + { input: this.tempHF, name: 't2' }, + { input: this.weights['b_f'], name: 'bias' } + ] + }) + + if (this.recurrentActivation !== 'linear') { + webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentForgetGateState, + inputs: [{ input: this.currentForgetGateStatePreactiv, name: 'x' }] + }) + } else { + this.currentForgetGateState = this.currentForgetGateStatePreactiv + } + + // output gate + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXO, + inputs: [{ input: this.currentX, name: 'A' }, { input: this.weights['W_o'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHO, + inputs: [{ input: this.previousHiddenState, name: 'A' }, { input: this.weights['U_o'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentOutputGateStatePreactiv, + inputs: [ + { input: this.tempXO, name: 't1' }, + { input: this.tempHO, name: 't2' }, + { input: this.weights['b_o'], name: 'bias' } + ] + }) + + if (this.recurrentActivation !== 'linear') { + webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentOutputGateState, + inputs: [{ input: this.currentOutputGateStatePreactiv, name: 'x' }] + }) + } else { + this.currentOutputGateState = this.currentOutputGateStatePreactiv + } + + // candidate + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXC, + inputs: [{ input: this.currentX, name: 'A' }, { input: this.weights['W_c'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHC, + inputs: [{ input: this.previousHiddenState, name: 'A' }, { input: this.weights['U_c'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentCandidatePreactiv, + inputs: [ + { input: this.tempXC, name: 't1' }, + { input: this.tempHC, name: 't2' }, + { input: this.weights['b_c'], name: 'bias' } + ] + }) + + if (this.activation !== 'linear') { + webgl2.runProgram({ + program: this.activationProgram, + output: this.currentCandidate, + inputs: [{ input: this.currentCandidatePreactiv, name: 'x' }] + }) + } else { + this.currentCandidate = this.currentCandidatePreactiv + } + + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentCandidateCopy, + inputs: [{ input: this.currentCandidate, name: 'source' }] + }) + + webgl2.runProgram({ + program: this.updateProgram, + output: this.currentCandidate, + inputs: [ + { input: this.currentCandidateCopy, name: 'c' }, + { input: this.previousCandidate, name: 'ctm1' }, + { input: this.currentInputGateState, name: 'i' }, + { input: this.currentForgetGateState, name: 'f' } + ] + }) + + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousCandidate, + inputs: [{ input: this.currentCandidate, name: 'source' }] + }) + + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentCandidatePreactiv, + inputs: [{ input: this.currentCandidate, name: 'source' }] + }) + + if (this.activation !== 'linear') { + webgl2.runProgram({ + program: this.activationProgram, + output: this.currentCandidate, + inputs: [{ input: this.currentCandidatePreactiv, name: 'x' }] + }) + } else { + this.currentCandidate = this.currentCandidatePreactiv + } + + webgl2.runProgram({ + program: this.gateProductProgram, + output: this.currentHiddenState, + inputs: [{ input: this.currentOutputGateState, name: 't1' }, { input: this.currentCandidate, name: 't2' }] + }) + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + const dimInputGate = this.weights['b_i'].glTextureShape[1] + const dimCandidate = this.weights['b_c'].glTextureShape[1] + const dimForgetGate = this.weights['b_f'].glTextureShape[1] + const dimOutputGate = this.weights['b_o'].glTextureShape[1] + + if (!this.currentInputGateState) { + this.currentInputGateState = new Tensor([], [dimInputGate]) + this.currentInputGateState.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentInputGateStatePreactiv) { + this.currentInputGateStatePreactiv = new Tensor([], [dimInputGate]) + this.currentInputGateStatePreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempXI) { + this.tempXI = new Tensor([], [dimInputGate]) + this.tempXI.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempHI) { + this.tempHI = new Tensor([], [dimInputGate]) + this.tempHI.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentForgetGateState) { + this.currentForgetGateState = new Tensor([], [dimForgetGate]) + this.currentForgetGateState.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentForgetGateStatePreactiv) { + this.currentForgetGateStatePreactiv = new Tensor([], [dimForgetGate]) + this.currentForgetGateStatePreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempXF) { + this.tempXF = new Tensor([], [dimForgetGate]) + this.tempXF.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempHF) { + this.tempHF = new Tensor([], [dimForgetGate]) + this.tempHF.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentOutputGateState) { + this.currentOutputGateState = new Tensor([], [dimOutputGate]) + this.currentOutputGateState.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentOutputGateStatePreactiv) { + this.currentOutputGateStatePreactiv = new Tensor([], [dimOutputGate]) + this.currentOutputGateStatePreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempXO) { + this.tempXO = new Tensor([], [dimOutputGate]) + this.tempXO.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempHO) { + this.tempHO = new Tensor([], [dimOutputGate]) + this.tempHO.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentCandidate) { + this.currentCandidate = new Tensor([], [dimCandidate]) + this.currentCandidate.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentCandidateCopy) { + this.currentCandidateCopy = new Tensor([], [dimCandidate]) + this.currentCandidateCopy.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentCandidatePreactiv) { + this.currentCandidatePreactiv = new Tensor([], [dimCandidate]) + this.currentCandidatePreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempXC) { + this.tempXC = new Tensor([], [dimCandidate]) + this.tempXC.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempHC) { + this.tempHC = new Tensor([], [dimCandidate]) + this.tempHC.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.previousCandidate || !this.stateful) { + this.previousCandidate = new Tensor([], [dimCandidate]) + this.previousCandidate.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new Tensor([], [dimCandidate]) + this.currentHiddenState.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.previousHiddenState) { + this.previousHiddenState = new Tensor([], [dimCandidate]) + this.previousHiddenState.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new Tensor([], [x.glTextureShape[0], dimCandidate]) + this.hiddenStateSequence.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new Tensor([], [x.glTextureShape[0], dimCandidate]) + this.hiddenStateSequenceCopy.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentX) { + this.currentX = new Tensor([], [x.glTextureShape[1]]) + this.currentX.createGLTexture({ type: '2d', format: 'float' }) + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i + + webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ input: x, name: 'x' }], + uniforms: [{ value: inputIndex, type: 'int', name: 'index' }] + }) + + this._stepGPU() + + if (this.returnSequences) { + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ input: this.hiddenStateSequence, name: 'source' }] + }) + webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ input: this.currentHiddenState, name: 'x' }, { input: this.hiddenStateSequenceCopy, name: 'y' }], + uniforms: [{ value: i, type: 'int', name: 'index' }] + }) + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence + } else { + this.output = this.currentHiddenState + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/recurrent/LSTM.update.glsl b/keras-js/src/layers/recurrent/LSTM.update.glsl new file mode 100644 index 0000000000..d6fe6e99fb --- /dev/null +++ b/keras-js/src/layers/recurrent/LSTM.update.glsl @@ -0,0 +1,22 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D c; +uniform sampler2D ctm1; +uniform sampler2D i; +uniform sampler2D f; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(c, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + float c_val = texelFetch(c, ivec2(out_x, out_y), 0).r; + float ctm1_val = texelFetch(ctm1, ivec2(out_x, out_y), 0).r; + float i_val = texelFetch(i, ivec2(out_x, out_y), 0).r; + float f_val = texelFetch(f, ivec2(out_x, out_y), 0).r; + + outColor = vec4(c_val * i_val + ctm1_val * f_val); +} diff --git a/keras-js/src/layers/recurrent/SimpleRNN.js b/keras-js/src/layers/recurrent/SimpleRNN.js new file mode 100644 index 0000000000..406ba49a05 --- /dev/null +++ b/keras-js/src/layers/recurrent/SimpleRNN.js @@ -0,0 +1,292 @@ +import * as activations from '../../activations' +import Tensor from '../../Tensor' +import Layer from '../../Layer' +import { webgl2 } from '../../WebGL2' +import { gemv } from 'ndarray-blas-level2' +import ops from 'ndarray-ops' +import cwise from 'cwise' +import copyTextureProgramSource from '../../webgl/copyTexture.glsl' +import matMulProgramSource from '../../webgl/matMul.glsl' +import * as activationProgramSources from '../../activations/programSources' +import gateSummationProgramSource from './gateSummation.glsl' +import timestepReadProgramSource from './timestepRead.glsl' +import timestepWriteProgramSource from './timestepWrite.glsl' + +/** + * SimpleRNN layer class + */ +export default class SimpleRNN extends Layer { + /** + * Creates a SimpleRNN layer + * + * @param {Object} [attrs] - layer attributes + * @param {number} [attrs.units] - output dimensionality + * @param {number} [attrs.activation] - activation function + * @param {number} [attrs.use_bias] - use bias + * @param {number} [attrs.return_sequences] - return the last output in the output sequence or the full sequence + * @param {number} [attrs.go_backwards] - process the input sequence backwards + * @param {number} [attrs.stateful] - whether to save the last state as the initial state for the next pass + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'SimpleRNN' + + const { + units = 1, + activation = 'tanh', + use_bias = true, + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs + + this.units = units + + // keep this.activation for Bidirectional wrapper layer to use + this.activation = activation + this.activationFunc = activations[activation] + + this.use_bias = use_bias + + this.returnSequences = return_sequences + this.goBackwards = go_backwards + this.stateful = stateful + + // Layer weights specification + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel'] + + // GPU setup + if (this.gpu) { + this.copyTextureProgram = webgl2.compileProgram(copyTextureProgramSource) + this.matMulProgram = webgl2.compileProgram(matMulProgramSource) + this.activationProgram = webgl2.compileProgram(activationProgramSources[this.activation]) + this.gateSummationProgram = webgl2.compileProgram(gateSummationProgramSource) + this.timestepReadProgram = webgl2.compileProgram(timestepReadProgramSource) + this.timestepWriteProgram = webgl2.compileProgram(timestepWriteProgramSource) + } + } + + /** + * Method for setting layer weights. Extends `super` method. Create empty bias if this.use_bias is false. + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + super.setWeights(weightsArr) + if (!this.use_bias) { + this.weights['bias'] = new Tensor([], [this.units]) + if (this.gpu) { + this.weights['bias'].createGLTexture({ type: '2d', format: 'float' }) + } + } + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + _combine = cwise({ + args: ['array', 'array', 'array', 'array'], + body: function(_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b + } + }) + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + const dimHiddenState = this.units + + const currentHiddenState = + this.stateful && this.currentHiddenState ? this.currentHiddenState : new Tensor([], [dimHiddenState]) + const tempXH = new Tensor([], [dimHiddenState]) + const tempHH = new Tensor([], [dimHiddenState]) + const previousHiddenState = new Tensor([], [dimHiddenState]) + + this.hiddenStateSequence = new Tensor([], [x.tensor.shape[0], dimHiddenState]) + + const currentX = new Tensor([], [x.tensor.shape[1]]) + + const _step = () => { + ops.assign(previousHiddenState.tensor, currentHiddenState.tensor) + + gemv(1, this.weights['kernel'].tensor.transpose(1, 0), currentX.tensor, 1, tempXH.tensor) + gemv(1, this.weights['recurrent_kernel'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHH.tensor) + this._combine(currentHiddenState.tensor, tempXH.tensor, tempHH.tensor, this.weights['bias'].tensor) + this.activationFunc(currentHiddenState) + } + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i + ops.assign(currentX.tensor, x.tensor.pick(inputIndex, null)) + + // clear temp tensors + const tempTensors = [tempXH, tempHH] + tempTensors.forEach(temp => ops.assigns(temp.tensor, 0)) + + // advance timestep + _step() + + if (this.returnSequences) { + ops.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor) + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence + } else { + this.output = currentHiddenState + } + + if (this.stateful) { + this.currentHiddenState = currentHiddenState + } + } + + /** + * Advance time step in _callGPU + */ + _stepGPU() { + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ input: this.currentHiddenState, name: 'source' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXH, + inputs: [{ input: this.currentX, name: 'A' }, { input: this.weights['kernel'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHH, + inputs: [{ input: this.previousHiddenState, name: 'A' }, { input: this.weights['recurrent_kernel'], name: 'B' }], + uniforms: [{ value: 0, type: 'bool', name: 'addC' }] + }) + + webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentHiddenStatePreactiv, + inputs: [ + { input: this.tempXH, name: 't1' }, + { input: this.tempHH, name: 't2' }, + { input: this.weights['bias'], name: 'bias' } + ] + }) + + if (this.activation !== 'linear') { + webgl2.runProgram({ + program: this.activationProgram, + output: this.currentHiddenState, + inputs: [{ input: this.currentHiddenStatePreactiv, name: 'x' }] + }) + } else { + this.currentHiddenState = this.currentHiddenStatePreactiv + } + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + + const dimHiddenState = this.units + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new Tensor([], [dimHiddenState]) + this.currentHiddenState.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.currentHiddenStatePreactiv) { + this.currentHiddenStatePreactiv = new Tensor([], [dimHiddenState]) + this.currentHiddenStatePreactiv.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.tempXH) { + this.tempXH = new Tensor([], [dimHiddenState]) + this.tempXH.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.tempHH) { + this.tempHH = new Tensor([], [dimHiddenState]) + this.tempHH.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.previousHiddenState) { + this.previousHiddenState = new Tensor([], [dimHiddenState]) + this.previousHiddenState.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new Tensor([], [x.glTextureShape[0], dimHiddenState]) + this.hiddenStateSequence.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new Tensor([], [x.glTextureShape[0], dimHiddenState]) + this.hiddenStateSequenceCopy.createGLTexture({ type: '2d', format: 'float' }) + } + + if (!this.currentX) { + this.currentX = new Tensor([], [x.glTextureShape[1]]) + this.currentX.createGLTexture({ type: '2d', format: 'float' }) + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i + + webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ input: x, name: 'x' }], + uniforms: [{ value: inputIndex, type: 'int', name: 'index' }] + }) + + this._stepGPU() + + if (this.returnSequences) { + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ input: this.hiddenStateSequence, name: 'source' }] + }) + webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ input: this.currentHiddenState, name: 'x' }, { input: this.hiddenStateSequenceCopy, name: 'y' }], + uniforms: [{ value: i, type: 'int', name: 'index' }] + }) + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence + } else { + this.output = this.currentHiddenState + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/recurrent/gateProduct.glsl b/keras-js/src/layers/recurrent/gateProduct.glsl new file mode 100644 index 0000000000..290dff1b8f --- /dev/null +++ b/keras-js/src/layers/recurrent/gateProduct.glsl @@ -0,0 +1,18 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D t1; +uniform sampler2D t2; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(t1, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r; + float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r; + + outColor = vec4(t1_val * t2_val); +} diff --git a/keras-js/src/layers/recurrent/gateSummation.glsl b/keras-js/src/layers/recurrent/gateSummation.glsl new file mode 100644 index 0000000000..ce49ee8dbb --- /dev/null +++ b/keras-js/src/layers/recurrent/gateSummation.glsl @@ -0,0 +1,20 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D t1; +uniform sampler2D t2; +uniform sampler2D bias; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(bias, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r; + float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r; + float bias_val = texelFetch(bias, ivec2(out_x, out_y), 0).r; + + outColor = vec4(t1_val + t2_val + bias_val); +} diff --git a/keras-js/src/layers/recurrent/index.js b/keras-js/src/layers/recurrent/index.js new file mode 100644 index 0000000000..d8eb2f2aa8 --- /dev/null +++ b/keras-js/src/layers/recurrent/index.js @@ -0,0 +1,5 @@ +import SimpleRNN from './SimpleRNN' +import LSTM from './LSTM' +import GRU from './GRU' + +export { SimpleRNN, LSTM, GRU } diff --git a/keras-js/src/layers/recurrent/timestepRead.glsl b/keras-js/src/layers/recurrent/timestepRead.glsl new file mode 100644 index 0000000000..24b308a9ef --- /dev/null +++ b/keras-js/src/layers/recurrent/timestepRead.glsl @@ -0,0 +1,14 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform int index; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(x, 0); + int out_x = int(float(size[0]) * outTex.x); + + outColor = vec4(texelFetch(x, ivec2(out_x, index), 0).r); +} diff --git a/keras-js/src/layers/recurrent/timestepWrite.glsl b/keras-js/src/layers/recurrent/timestepWrite.glsl new file mode 100644 index 0000000000..27c5534bf4 --- /dev/null +++ b/keras-js/src/layers/recurrent/timestepWrite.glsl @@ -0,0 +1,20 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform sampler2D y; +uniform int index; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(y, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + if (out_y == index) { + outColor = vec4(texelFetch(x, ivec2(out_x, 0), 0).r); + } else { + outColor = vec4(texelFetch(y, ivec2(out_x, out_y), 0).r); + } +} diff --git a/keras-js/src/layers/wrappers/Bidirectional.ave.glsl b/keras-js/src/layers/wrappers/Bidirectional.ave.glsl new file mode 100644 index 0000000000..cb82324942 --- /dev/null +++ b/keras-js/src/layers/wrappers/Bidirectional.ave.glsl @@ -0,0 +1,18 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D forward; +uniform sampler2D backward; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(forward, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r; + float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r; + + outColor = vec4(0.5 * (forward_val + backward_val)); +} diff --git a/keras-js/src/layers/wrappers/Bidirectional.concat.glsl b/keras-js/src/layers/wrappers/Bidirectional.concat.glsl new file mode 100644 index 0000000000..1236df7fae --- /dev/null +++ b/keras-js/src/layers/wrappers/Bidirectional.concat.glsl @@ -0,0 +1,19 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D forward; +uniform sampler2D backward; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(forward, 0); + int out_x = int(float(size[0] * 2) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + if (out_x >= 0 && out_x < size[0]) { + outColor = vec4(texelFetch(forward, ivec2(out_x, out_y), 0).r); + } else { + outColor = vec4(texelFetch(backward, ivec2(out_x - size[0], size[1] - out_y - 1), 0).r); + } +} diff --git a/keras-js/src/layers/wrappers/Bidirectional.js b/keras-js/src/layers/wrappers/Bidirectional.js new file mode 100644 index 0000000000..4793049d29 --- /dev/null +++ b/keras-js/src/layers/wrappers/Bidirectional.js @@ -0,0 +1,190 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import * as recurrentLayers from '../recurrent' +import copyTextureProgramSource from '../../webgl/copyTexture.glsl' +import concatMergeProgramSource from './Bidirectional.concat.glsl' +import sumMergeProgramSource from './Bidirectional.sum.glsl' +import mulMergeProgramSource from './Bidirectional.mul.glsl' +import aveMergeProgramSource from './Bidirectional.ave.glsl' + +/** + * Bidirectional wrapper layer class + */ +export default class Bidirectional extends Layer { + /** + * Creates a Bidirectional wrapper layer + * + * @param {Object} [attrs] - layer config attributes + * @param {string} [attrs.merge_mode] - merge mode of component layers + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'Bidirectional' + + const { layer, merge_mode = 'concat' } = attrs + + if (!layer) { + this.throwError('wrapped layer is undefined.') + } + if (!['SimpleRNN', 'GRU', 'LSTM'].includes(layer.class_name)) { + this.throwError(`cannot wrap ${layer.class_name} layer.`) + } + if (!['concat', 'sum', 'mul', 'ave'].includes(merge_mode)) { + this.throwError(`merge_mode ${merge_mode} not supported.`) + } + + const forwardLayerAttrs = Object.assign({}, layer.config, { gpu: attrs.gpu }) + const backwardLayerAttrs = Object.assign({}, layer.config, { gpu: attrs.gpu }) + backwardLayerAttrs.go_backwards = !backwardLayerAttrs.go_backwards + this.forwardLayer = new recurrentLayers[layer.class_name](forwardLayerAttrs) + this.backwardLayer = new recurrentLayers[layer.class_name](backwardLayerAttrs) + + // prevent GPU -> CPU data transfer by specifying non-empty outbound nodes array on internal layers + this.forwardLayer.outbound = [null] + this.backwardLayer.outbound = [null] + + this.mergeMode = merge_mode + this.returnSequences = layer.config.return_sequences + + // GPU setup + if (this.gpu) { + this.copyTextureProgram = webgl2.compileProgram(copyTextureProgramSource) + if (this.mergeMode === 'concat') { + this.mergeProgram = webgl2.compileProgram(concatMergeProgramSource) + } else if (this.mergeMode === 'sum') { + this.mergeProgram = webgl2.compileProgram(sumMergeProgramSource) + } else if (this.mergeMode === 'mul') { + this.mergeProgram = webgl2.compileProgram(mulMergeProgramSource) + } else if (this.mergeMode === 'ave') { + this.mergeProgram = webgl2.compileProgram(aveMergeProgramSource) + } + } + } + + /** + * Method for setting layer weights - passes weights to the wrapped layer + * + * Here, the weights array is concatenated from the forward layer and the backward layer + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + this.forwardLayer.setWeights(weightsArr.slice(0, weightsArr.length / 2)) + this.backwardLayer.setWeights(weightsArr.slice(weightsArr.length / 2)) + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + this.forwardLayer._callCPU(new Tensor(x.tensor.data, x.tensor.shape)) + this.backwardLayer._callCPU(new Tensor(x.tensor.data, x.tensor.shape)) + const forwardOutput = this.forwardLayer.output + const backwardOutput = this.backwardLayer.output + + // when returnSequences = true, reverse results of backwardLayer + if (this.returnSequences) { + backwardOutput.tensor = backwardOutput.tensor.step(-1) + } + + const outShape = forwardOutput.tensor.shape.slice() + if (this.mergeMode === 'concat') { + outShape[outShape.length - 1] += backwardOutput.tensor.shape[outShape.length - 1] + } + this.output = new Tensor([], outShape) + + if (this.mergeMode === 'concat') { + if (this.returnSequences) { + ops.assign(this.output.tensor.hi(outShape[0], forwardOutput.tensor.shape[1]).lo(0, 0), forwardOutput.tensor) + ops.assign( + this.output.tensor.hi(outShape[0], outShape[1]).lo(0, forwardOutput.tensor.shape[1]), + backwardOutput.tensor + ) + } else { + ops.assign(this.output.tensor.hi(forwardOutput.tensor.shape[0]).lo(0), forwardOutput.tensor) + ops.assign(this.output.tensor.hi(outShape[0]).lo(forwardOutput.tensor.shape[0]), backwardOutput.tensor) + } + } else if (this.mergeMode === 'sum') { + ops.addeq(this.output.tensor, forwardOutput.tensor) + ops.addeq(this.output.tensor, backwardOutput.tensor) + } else if (this.mergeMode === 'mul') { + ops.assigns(this.output.tensor, 1) + ops.muleq(this.output.tensor, forwardOutput.tensor) + ops.muleq(this.output.tensor, backwardOutput.tensor) + } else if (this.mergeMode === 'ave') { + ops.addeq(this.output.tensor, forwardOutput.tensor) + ops.addeq(this.output.tensor, backwardOutput.tensor) + ops.divseq(this.output.tensor, 2) + } + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ type: '2d', format: 'float' }) + } + if (!this.inputCopy) { + this.inputCopy = new Tensor([], x.glTextureShape) + this.inputCopy.createGLTexture({ type: '2d', format: 'float' }) + } + + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.inputCopy, + inputs: [{ input: x, name: 'source' }] + }) + + // run internal component layers + this.forwardLayer._callGPU(x) + this.backwardLayer._callGPU(this.inputCopy) + const forwardOutput = this.forwardLayer.output + const backwardOutput = this.backwardLayer.output + + const outShape = forwardOutput.glTextureShape.slice() + if (this.mergeMode === 'concat') { + outShape[1] += backwardOutput.glTextureShape[1] + } + if (!this.output) { + this.output = new Tensor([], outShape) + this.output.createGLTexture({ type: '2d', format: 'float' }) + if (!this.returnSequences) { + this.output.is1D = true + } + } + + // merge forward and backward outputs + webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: [{ input: forwardOutput, name: 'forward' }, { input: backwardOutput, name: 'backward' }] + }) + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + } + } +} diff --git a/keras-js/src/layers/wrappers/Bidirectional.mul.glsl b/keras-js/src/layers/wrappers/Bidirectional.mul.glsl new file mode 100644 index 0000000000..24ec8813d3 --- /dev/null +++ b/keras-js/src/layers/wrappers/Bidirectional.mul.glsl @@ -0,0 +1,18 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D forward; +uniform sampler2D backward; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(forward, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r; + float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r; + + outColor = vec4(forward_val * backward_val); +} diff --git a/keras-js/src/layers/wrappers/Bidirectional.sum.glsl b/keras-js/src/layers/wrappers/Bidirectional.sum.glsl new file mode 100644 index 0000000000..3fadd7498c --- /dev/null +++ b/keras-js/src/layers/wrappers/Bidirectional.sum.glsl @@ -0,0 +1,18 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D forward; +uniform sampler2D backward; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(forward, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r; + float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r; + + outColor = vec4(forward_val + backward_val); +} diff --git a/keras-js/src/layers/wrappers/TimeDistributed.copySliceOutput.glsl b/keras-js/src/layers/wrappers/TimeDistributed.copySliceOutput.glsl new file mode 100644 index 0000000000..ff5894b098 --- /dev/null +++ b/keras-js/src/layers/wrappers/TimeDistributed.copySliceOutput.glsl @@ -0,0 +1,21 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D outputCopy; +uniform sampler2D sliceOutput; +uniform int t; +uniform int timesteps; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(sliceOutput, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(timesteps) * outTex.y); + + if (t == out_y) { + outColor = vec4(texelFetch(sliceOutput, ivec2(out_x, 0), 0).r); + } else { + outColor = texelFetch(outputCopy, ivec2(out_x, out_y), 0); + } +} diff --git a/keras-js/src/layers/wrappers/TimeDistributed.js b/keras-js/src/layers/wrappers/TimeDistributed.js new file mode 100644 index 0000000000..e0f2204f9b --- /dev/null +++ b/keras-js/src/layers/wrappers/TimeDistributed.js @@ -0,0 +1,301 @@ +import Layer from '../../Layer' +import Tensor from '../../Tensor' +import { webgl2 } from '../../WebGL2' +import ops from 'ndarray-ops' +import * as layers from '../' +import copyTextureProgramSource from '../../webgl/copyTexture.glsl' +import mapInputProgramSource from '../../webgl/mapInput.glsl' +import selectSliceProgramSource from './TimeDistributed.selectSlice.glsl' +import copySliceOutputProgramSource from './TimeDistributed.copySliceOutput.glsl' +import mapSliceOutputProgramSource from './TimeDistributed.mapSliceOutput.glsl' + +/** + * TimeDistributed wrapper layer class + */ +export default class TimeDistributed extends Layer { + /** + * Creates a TimeDistributed wrapper layer + * + * @param {Object} [attrs] - layer config attributes + */ + constructor(attrs = {}) { + super(attrs) + this.layerClass = 'TimeDistributed' + + const { layer } = attrs + + if (!layer) { + this.throwError('wrapped layer is undefined.') + } + + const wrappedLayerAttrs = Object.assign({}, layer.config, { gpu: attrs.gpu }) + this.wrappedLayer = new layers[layer.class_name](wrappedLayerAttrs) + + // prevent GPU -> CPU data transfer by specifying non-empty outbound nodes array on internal layer + this.wrappedLayer.outbound = [null] + + // GPU setup + if (this.gpu) { + this.copyTextureProgram = webgl2.compileProgram(copyTextureProgramSource) + this.mapInputProgram = webgl2.compileProgram(mapInputProgramSource) + this.selectSliceProgram = webgl2.compileProgram(selectSliceProgramSource) + this.copySliceOutputProgram = webgl2.compileProgram(copySliceOutputProgramSource) + this.mapSliceOutputProgram = webgl2.compileProgram(mapSliceOutputProgramSource) + } + } + + /** + * Method for setting layer weights + * Passes weights to the wrapped layer + * + * @param {Tensor[]} weightsArr - array of weights which are instances of Tensor + */ + setWeights(weightsArr) { + this.wrappedLayer.setWeights(weightsArr) + } + + /** + * Layer computational logic + * + * @param {Tensor} x + * @returns {Tensor} + */ + call(x) { + if (this.gpu) { + this._callGPU(x) + } else { + this._callCPU(x) + } + return this.output + } + + /** + * CPU call + * + * @param {Tensor} x + */ + _callCPU(x) { + const stepShape = [...x.tensor.shape.slice(1)] + const step = new Tensor([], stepShape) + ops.assign(step.tensor, x.tensor.pick(0, ...Array(stepShape.length).fill(null))) + let stepOutput = this.wrappedLayer.call(step) + const stepOutputShape = stepOutput.tensor.shape.slice() + this.output = new Tensor([], [x.tensor.shape[0], ...stepOutputShape]) + ops.assign(this.output.tensor.pick(0, ...Array(stepOutputShape.length).fill(null)), stepOutput.tensor) + for (let i = 1, timesteps = x.tensor.shape[0]; i < timesteps; i++) { + ops.assign(step.tensor, x.tensor.pick(i, ...Array(stepShape.length).fill(null))) + stepOutput = this.wrappedLayer.call(step) + ops.assign(this.output.tensor.pick(i, ...Array(stepOutputShape.length).fill(null)), stepOutput.tensor) + } + } + + /** + * Creates row/col index mappings to map input texture to time-distributed slices + * + * @param {Object} indicesForReshaped + */ + _createIndexMap(indicesForReshaped) { + if (this.indexMaps) { + return + } + + const indices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + this.indexMaps = [] + + const timesteps = this.inputShape[0] + const sliceShape = this.inputShape.slice(1) + for (let t = 0; t < timesteps; t++) { + const sliceIndices = new Tensor([], sliceShape, { type: Int32Array }) + ops.assign(sliceIndices.tensor, indices.tensor.pick(t, ...Array(sliceShape.length).fill(null))) + sliceIndices.reshapeTo2DSquare() + sliceIndices.createGLTexture({ type: '2d', format: 'int' }) + this.indexMaps.push(sliceIndices) + } + } + + /** + * Creates row/col index mappings to map time-distributed slices to output texture + * + * @param {Object} indicesForReshaped + */ + _createOutputIndexMap(indicesForReshaped) { + if (this.outputIndexMaps) { + return + } + + const outputSliceIndices = new Tensor(indicesForReshaped.data, indicesForReshaped.shape, { type: Int32Array }) + + this.outputIndexMaps = [] + + const timesteps = this.outputShape[0] + const sliceShape = this.outputShape.slice(1) + for (let t = 0; t < timesteps; t++) { + const outputIndices = new Tensor([], this.outputShape, { type: Int32Array }) + ops.assigns(outputIndices.tensor, -1) + ops.assign(outputIndices.tensor.pick(t, ...Array(sliceShape.length).fill(null)), outputSliceIndices.tensor) + outputIndices.reshapeTo2DSquare() + outputIndices.createGLTexture({ type: '2d', format: 'int' }) + this.outputIndexMaps.push(outputIndices) + } + } + + /** + * GPU call + * + * @param {Tensor} x + */ + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape + } else { + this.inputShape = x.tensor.shape + } + + if (!x.glTexture) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ type: '2d', format: 'float' }) + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2DSquare() + x.createGLTexture({ type: '2d', format: 'float' }) + } + } + + if (this.inputShape.length > 2) { + this._createIndexMap(x.indicesForReshaped) + } + + const timesteps = this.inputShape[0] + const sliceShape = this.inputShape.slice(1) + + if (!this.slice) { + this.slice = new Tensor([], sliceShape) + if (sliceShape.length <= 2) { + this.slice.createGLTexture({ type: '2d', format: 'float' }) + } else { + this.slice.reshapeTo2DSquare() + this.slice.createGLTexture({ type: '2d', format: 'float' }) + } + } + + if (this.inputShape.length <= 2) { + webgl2.runProgram({ + program: this.selectSliceProgram, + output: this.slice, + inputs: [{ input: x, name: 'x' }], + uniforms: [{ value: 0, type: 'int', name: 't' }] + }) + } else { + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.slice, + inputs: [{ input: x, name: 'x' }, { input: this.indexMaps[0], name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + } + + this.wrappedLayer._callGPU(this.slice) + this.sliceOutput = this.wrappedLayer.output + + if (!this.output) { + if (this.inputShape.length <= 2) { + this.outputShape = [timesteps, this.sliceOutput.glTextureShape[1]] + this.output = new Tensor([], this.outputShape) + this.outputCopy = new Tensor([], this.outputShape) + this.output.createGLTexture({ type: '2d', format: 'float' }) + this.outputCopy.createGLTexture({ type: '2d', format: 'float' }) + } else { + this.outputShape = [timesteps, ...this.sliceOutput.originalShape] + this.output = new Tensor([], this.outputShape) + this.outputCopy = new Tensor([], this.outputShape) + this.output.reshapeTo2DSquare() + this.outputCopy.reshapeTo2DSquare() + this.output.createGLTexture({ type: '2d', format: 'float' }) + this.outputCopy.createGLTexture({ type: '2d', format: 'float' }) + + this._createOutputIndexMap(this.sliceOutput.indicesForReshaped) + } + } + + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.outputCopy, + inputs: [{ input: this.output, name: 'source' }] + }) + + if (this.inputShape.length <= 2) { + webgl2.runProgram({ + program: this.copySliceOutputProgram, + output: this.output, + inputs: [{ input: this.outputCopy, name: 'outputCopy' }, { input: this.sliceOutput, name: 'sliceOutput' }], + uniforms: [{ value: 0, type: 'int', name: 't' }, { value: timesteps, type: 'int', name: 'timesteps' }] + }) + } else { + webgl2.runProgram({ + program: this.mapSliceOutputProgram, + output: this.output, + inputs: [ + { input: this.outputCopy, name: 'outputCopy' }, + { input: this.sliceOutput, name: 'sliceOutput' }, + { input: this.outputIndexMaps[0], name: 'indexMap' } + ] + }) + } + + for (let i = 1; i < timesteps; i++) { + if (this.inputShape.length <= 2) { + webgl2.runProgram({ + program: this.selectSliceProgram, + output: this.slice, + inputs: [{ input: x, name: 'x' }], + uniforms: [{ value: i, type: 'int', name: 't' }] + }) + } else { + webgl2.runProgram({ + program: this.mapInputProgram, + output: this.slice, + inputs: [{ input: x, name: 'x' }, { input: this.indexMaps[i], name: 'indexMap' }], + uniforms: [{ value: x.glTextureShape[1], type: 'int', name: 'inputCols' }] + }) + } + + this.wrappedLayer._callGPU(this.slice) + this.sliceOutput = this.wrappedLayer.output + + webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.outputCopy, + inputs: [{ input: this.output, name: 'source' }] + }) + + if (this.inputShape.length <= 2) { + webgl2.runProgram({ + program: this.copySliceOutputProgram, + output: this.output, + inputs: [{ input: this.outputCopy, name: 'outputCopy' }, { input: this.sliceOutput, name: 'sliceOutput' }], + uniforms: [{ value: i, type: 'int', name: 't' }, { value: timesteps, type: 'int', name: 'timesteps' }] + }) + } else { + webgl2.runProgram({ + program: this.mapSliceOutputProgram, + output: this.output, + inputs: [ + { input: this.outputCopy, name: 'outputCopy' }, + { input: this.sliceOutput, name: 'sliceOutput' }, + { input: this.outputIndexMaps[i], name: 'indexMap' } + ] + }) + } + } + + // GPU -> CPU data transfer + if (this.outbound.length === 0) { + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare() + } + } + } +} diff --git a/keras-js/src/layers/wrappers/TimeDistributed.mapSliceOutput.glsl b/keras-js/src/layers/wrappers/TimeDistributed.mapSliceOutput.glsl new file mode 100644 index 0000000000..909141f889 --- /dev/null +++ b/keras-js/src/layers/wrappers/TimeDistributed.mapSliceOutput.glsl @@ -0,0 +1,26 @@ +#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D outputCopy; +uniform sampler2D sliceOutput; +uniform isampler2D indexMap; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(outputCopy, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r; + + if (index != -1) { + int rowIndex = int(floor(float(index) / float(textureSize(sliceOutput, 0)[0]))); + int colIndex = int(mod(float(index), float(textureSize(sliceOutput, 0)[0]))); + float val = texelFetch(sliceOutput, ivec2(colIndex, rowIndex), 0).r; + outColor = vec4(val); + } else { + outColor = texelFetch(outputCopy, ivec2(out_x, out_y), 0); + } +} diff --git a/keras-js/src/layers/wrappers/TimeDistributed.selectSlice.glsl b/keras-js/src/layers/wrappers/TimeDistributed.selectSlice.glsl new file mode 100644 index 0000000000..0f2278d327 --- /dev/null +++ b/keras-js/src/layers/wrappers/TimeDistributed.selectSlice.glsl @@ -0,0 +1,14 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D x; +uniform int t; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(x, 0); + int out_x = int(float(size[0]) * outTex.x); + + outColor = vec4(texelFetch(x, ivec2(out_x, t), 0).r); +} diff --git a/keras-js/src/layers/wrappers/index.js b/keras-js/src/layers/wrappers/index.js new file mode 100644 index 0000000000..1ccf564d22 --- /dev/null +++ b/keras-js/src/layers/wrappers/index.js @@ -0,0 +1,4 @@ +import TimeDistributed from './TimeDistributed' +import Bidirectional from './Bidirectional' + +export { TimeDistributed, Bidirectional } diff --git a/keras-js/src/proto.js b/keras-js/src/proto.js new file mode 100644 index 0000000000..6df6d0d009 --- /dev/null +++ b/keras-js/src/proto.js @@ -0,0 +1,676 @@ +/*eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins*/ +import * as $protobuf from "protobufjs/minimal"; + +// Common aliases +const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + +// Exported root namespace +const $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); + +export const Weights = $root.Weights = (() => { + + /** + * Properties of a Weights. + * @exports IWeights + * @interface IWeights + * @property {string} [layerName] Weights layerName + * @property {string} [weightName] Weights weightName + * @property {Array.} [shape] Weights shape + * @property {string} [type] Weights type + * @property {Uint8Array} [data] Weights data + * @property {number} [quantizeMin] Weights quantizeMin + * @property {number} [quantizeMax] Weights quantizeMax + */ + + /** + * Constructs a new Weights. + * @exports Weights + * @classdesc Represents a Weights. + * @constructor + * @param {IWeights=} [properties] Properties to set + */ + function Weights(properties) { + this.shape = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Weights layerName. + * @member {string}layerName + * @memberof Weights + * @instance + */ + Weights.prototype.layerName = ""; + + /** + * Weights weightName. + * @member {string}weightName + * @memberof Weights + * @instance + */ + Weights.prototype.weightName = ""; + + /** + * Weights shape. + * @member {Array.}shape + * @memberof Weights + * @instance + */ + Weights.prototype.shape = $util.emptyArray; + + /** + * Weights type. + * @member {string}type + * @memberof Weights + * @instance + */ + Weights.prototype.type = ""; + + /** + * Weights data. + * @member {Uint8Array}data + * @memberof Weights + * @instance + */ + Weights.prototype.data = $util.newBuffer([]); + + /** + * Weights quantizeMin. + * @member {number}quantizeMin + * @memberof Weights + * @instance + */ + Weights.prototype.quantizeMin = 0; + + /** + * Weights quantizeMax. + * @member {number}quantizeMax + * @memberof Weights + * @instance + */ + Weights.prototype.quantizeMax = 0; + + /** + * Creates a new Weights instance using the specified properties. + * @function create + * @memberof Weights + * @static + * @param {IWeights=} [properties] Properties to set + * @returns {Weights} Weights instance + */ + Weights.create = function create(properties) { + return new Weights(properties); + }; + + /** + * Encodes the specified Weights message. Does not implicitly {@link Weights.verify|verify} messages. + * @function encode + * @memberof Weights + * @static + * @param {IWeights} message Weights message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Weights.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.layerName != null && message.hasOwnProperty("layerName")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.layerName); + if (message.weightName != null && message.hasOwnProperty("weightName")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.weightName); + if (message.shape != null && message.shape.length) { + writer.uint32(/* id 3, wireType 2 =*/26).fork(); + for (let i = 0; i < message.shape.length; ++i) + writer.uint32(message.shape[i]); + writer.ldelim(); + } + if (message.type != null && message.hasOwnProperty("type")) + writer.uint32(/* id 4, wireType 2 =*/34).string(message.type); + if (message.data != null && message.hasOwnProperty("data")) + writer.uint32(/* id 5, wireType 2 =*/42).bytes(message.data); + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) + writer.uint32(/* id 6, wireType 5 =*/53).float(message.quantizeMin); + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) + writer.uint32(/* id 7, wireType 5 =*/61).float(message.quantizeMax); + return writer; + }; + + /** + * Encodes the specified Weights message, length delimited. Does not implicitly {@link Weights.verify|verify} messages. + * @function encodeDelimited + * @memberof Weights + * @static + * @param {IWeights} message Weights message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Weights.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Weights message from the specified reader or buffer. + * @function decode + * @memberof Weights + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {Weights} Weights + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Weights.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.Weights(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.layerName = reader.string(); + break; + case 2: + message.weightName = reader.string(); + break; + case 3: + if (!(message.shape && message.shape.length)) + message.shape = []; + if ((tag & 7) === 2) { + let end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.shape.push(reader.uint32()); + } else + message.shape.push(reader.uint32()); + break; + case 4: + message.type = reader.string(); + break; + case 5: + message.data = reader.bytes(); + break; + case 6: + message.quantizeMin = reader.float(); + break; + case 7: + message.quantizeMax = reader.float(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Weights message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof Weights + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {Weights} Weights + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Weights.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Weights message. + * @function verify + * @memberof Weights + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Weights.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.layerName != null && message.hasOwnProperty("layerName")) + if (!$util.isString(message.layerName)) + return "layerName: string expected"; + if (message.weightName != null && message.hasOwnProperty("weightName")) + if (!$util.isString(message.weightName)) + return "weightName: string expected"; + if (message.shape != null && message.hasOwnProperty("shape")) { + if (!Array.isArray(message.shape)) + return "shape: array expected"; + for (let i = 0; i < message.shape.length; ++i) + if (!$util.isInteger(message.shape[i])) + return "shape: integer[] expected"; + } + if (message.type != null && message.hasOwnProperty("type")) + if (!$util.isString(message.type)) + return "type: string expected"; + if (message.data != null && message.hasOwnProperty("data")) + if (!(message.data && typeof message.data.length === "number" || $util.isString(message.data))) + return "data: buffer expected"; + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) + if (typeof message.quantizeMin !== "number") + return "quantizeMin: number expected"; + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) + if (typeof message.quantizeMax !== "number") + return "quantizeMax: number expected"; + return null; + }; + + /** + * Creates a Weights message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof Weights + * @static + * @param {Object.} object Plain object + * @returns {Weights} Weights + */ + Weights.fromObject = function fromObject(object) { + if (object instanceof $root.Weights) + return object; + let message = new $root.Weights(); + if (object.layerName != null) + message.layerName = String(object.layerName); + if (object.weightName != null) + message.weightName = String(object.weightName); + if (object.shape) { + if (!Array.isArray(object.shape)) + throw TypeError(".Weights.shape: array expected"); + message.shape = []; + for (let i = 0; i < object.shape.length; ++i) + message.shape[i] = object.shape[i] >>> 0; + } + if (object.type != null) + message.type = String(object.type); + if (object.data != null) + if (typeof object.data === "string") + $util.base64.decode(object.data, message.data = $util.newBuffer($util.base64.length(object.data)), 0); + else if (object.data.length) + message.data = object.data; + if (object.quantizeMin != null) + message.quantizeMin = Number(object.quantizeMin); + if (object.quantizeMax != null) + message.quantizeMax = Number(object.quantizeMax); + return message; + }; + + /** + * Creates a plain object from a Weights message. Also converts values to other types if specified. + * @function toObject + * @memberof Weights + * @static + * @param {Weights} message Weights + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Weights.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) + object.shape = []; + if (options.defaults) { + object.layerName = ""; + object.weightName = ""; + object.type = ""; + object.data = options.bytes === String ? "" : []; + object.quantizeMin = 0; + object.quantizeMax = 0; + } + if (message.layerName != null && message.hasOwnProperty("layerName")) + object.layerName = message.layerName; + if (message.weightName != null && message.hasOwnProperty("weightName")) + object.weightName = message.weightName; + if (message.shape && message.shape.length) { + object.shape = []; + for (let j = 0; j < message.shape.length; ++j) + object.shape[j] = message.shape[j]; + } + if (message.type != null && message.hasOwnProperty("type")) + object.type = message.type; + if (message.data != null && message.hasOwnProperty("data")) + object.data = options.bytes === String ? $util.base64.encode(message.data, 0, message.data.length) : options.bytes === Array ? Array.prototype.slice.call(message.data) : message.data; + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) + object.quantizeMin = options.json && !isFinite(message.quantizeMin) ? String(message.quantizeMin) : message.quantizeMin; + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) + object.quantizeMax = options.json && !isFinite(message.quantizeMax) ? String(message.quantizeMax) : message.quantizeMax; + return object; + }; + + /** + * Converts this Weights to JSON. + * @function toJSON + * @memberof Weights + * @instance + * @returns {Object.} JSON object + */ + Weights.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Weights; +})(); + +export const Model = $root.Model = (() => { + + /** + * Properties of a Model. + * @exports IModel + * @interface IModel + * @property {string} [id] Model id + * @property {string} [name] Model name + * @property {string} [kerasVersion] Model kerasVersion + * @property {string} [backend] Model backend + * @property {string} [modelConfig] Model modelConfig + * @property {Array.} [modelWeights] Model modelWeights + */ + + /** + * Constructs a new Model. + * @exports Model + * @classdesc Represents a Model. + * @constructor + * @param {IModel=} [properties] Properties to set + */ + function Model(properties) { + this.modelWeights = []; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * Model id. + * @member {string}id + * @memberof Model + * @instance + */ + Model.prototype.id = ""; + + /** + * Model name. + * @member {string}name + * @memberof Model + * @instance + */ + Model.prototype.name = ""; + + /** + * Model kerasVersion. + * @member {string}kerasVersion + * @memberof Model + * @instance + */ + Model.prototype.kerasVersion = ""; + + /** + * Model backend. + * @member {string}backend + * @memberof Model + * @instance + */ + Model.prototype.backend = ""; + + /** + * Model modelConfig. + * @member {string}modelConfig + * @memberof Model + * @instance + */ + Model.prototype.modelConfig = ""; + + /** + * Model modelWeights. + * @member {Array.}modelWeights + * @memberof Model + * @instance + */ + Model.prototype.modelWeights = $util.emptyArray; + + /** + * Creates a new Model instance using the specified properties. + * @function create + * @memberof Model + * @static + * @param {IModel=} [properties] Properties to set + * @returns {Model} Model instance + */ + Model.create = function create(properties) { + return new Model(properties); + }; + + /** + * Encodes the specified Model message. Does not implicitly {@link Model.verify|verify} messages. + * @function encode + * @memberof Model + * @static + * @param {IModel} message Model message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Model.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.id != null && message.hasOwnProperty("id")) + writer.uint32(/* id 1, wireType 2 =*/10).string(message.id); + if (message.name != null && message.hasOwnProperty("name")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.name); + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) + writer.uint32(/* id 3, wireType 2 =*/26).string(message.kerasVersion); + if (message.backend != null && message.hasOwnProperty("backend")) + writer.uint32(/* id 4, wireType 2 =*/34).string(message.backend); + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) + writer.uint32(/* id 5, wireType 2 =*/42).string(message.modelConfig); + if (message.modelWeights != null && message.modelWeights.length) + for (let i = 0; i < message.modelWeights.length; ++i) + $root.Weights.encode(message.modelWeights[i], writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified Model message, length delimited. Does not implicitly {@link Model.verify|verify} messages. + * @function encodeDelimited + * @memberof Model + * @static + * @param {IModel} message Model message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Model.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a Model message from the specified reader or buffer. + * @function decode + * @memberof Model + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {Model} Model + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Model.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.Model(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.id = reader.string(); + break; + case 2: + message.name = reader.string(); + break; + case 3: + message.kerasVersion = reader.string(); + break; + case 4: + message.backend = reader.string(); + break; + case 5: + message.modelConfig = reader.string(); + break; + case 6: + if (!(message.modelWeights && message.modelWeights.length)) + message.modelWeights = []; + message.modelWeights.push($root.Weights.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a Model message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof Model + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {Model} Model + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Model.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a Model message. + * @function verify + * @memberof Model + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + Model.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.id != null && message.hasOwnProperty("id")) + if (!$util.isString(message.id)) + return "id: string expected"; + if (message.name != null && message.hasOwnProperty("name")) + if (!$util.isString(message.name)) + return "name: string expected"; + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) + if (!$util.isString(message.kerasVersion)) + return "kerasVersion: string expected"; + if (message.backend != null && message.hasOwnProperty("backend")) + if (!$util.isString(message.backend)) + return "backend: string expected"; + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) + if (!$util.isString(message.modelConfig)) + return "modelConfig: string expected"; + if (message.modelWeights != null && message.hasOwnProperty("modelWeights")) { + if (!Array.isArray(message.modelWeights)) + return "modelWeights: array expected"; + for (let i = 0; i < message.modelWeights.length; ++i) { + let error = $root.Weights.verify(message.modelWeights[i]); + if (error) + return "modelWeights." + error; + } + } + return null; + }; + + /** + * Creates a Model message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof Model + * @static + * @param {Object.} object Plain object + * @returns {Model} Model + */ + Model.fromObject = function fromObject(object) { + if (object instanceof $root.Model) + return object; + let message = new $root.Model(); + if (object.id != null) + message.id = String(object.id); + if (object.name != null) + message.name = String(object.name); + if (object.kerasVersion != null) + message.kerasVersion = String(object.kerasVersion); + if (object.backend != null) + message.backend = String(object.backend); + if (object.modelConfig != null) + message.modelConfig = String(object.modelConfig); + if (object.modelWeights) { + if (!Array.isArray(object.modelWeights)) + throw TypeError(".Model.modelWeights: array expected"); + message.modelWeights = []; + for (let i = 0; i < object.modelWeights.length; ++i) { + if (typeof object.modelWeights[i] !== "object") + throw TypeError(".Model.modelWeights: object expected"); + message.modelWeights[i] = $root.Weights.fromObject(object.modelWeights[i]); + } + } + return message; + }; + + /** + * Creates a plain object from a Model message. Also converts values to other types if specified. + * @function toObject + * @memberof Model + * @static + * @param {Model} message Model + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + Model.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.arrays || options.defaults) + object.modelWeights = []; + if (options.defaults) { + object.id = ""; + object.name = ""; + object.kerasVersion = ""; + object.backend = ""; + object.modelConfig = ""; + } + if (message.id != null && message.hasOwnProperty("id")) + object.id = message.id; + if (message.name != null && message.hasOwnProperty("name")) + object.name = message.name; + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) + object.kerasVersion = message.kerasVersion; + if (message.backend != null && message.hasOwnProperty("backend")) + object.backend = message.backend; + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) + object.modelConfig = message.modelConfig; + if (message.modelWeights && message.modelWeights.length) { + object.modelWeights = []; + for (let j = 0; j < message.modelWeights.length; ++j) + object.modelWeights[j] = $root.Weights.toObject(message.modelWeights[j], options); + } + return object; + }; + + /** + * Converts this Model to JSON. + * @function toJSON + * @memberof Model + * @instance + * @returns {Object.} JSON object + */ + Model.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Model; +})(); + +export { $root as default }; diff --git a/keras-js/src/utils/tensorUtils.js b/keras-js/src/utils/tensorUtils.js new file mode 100644 index 0000000000..36c6455bbc --- /dev/null +++ b/keras-js/src/utils/tensorUtils.js @@ -0,0 +1,89 @@ +import ndarray from 'ndarray' +import ops from 'ndarray-ops' +import _ from 'lodash' + +/** + * Function to throw error if specified shape is incompatible with data + * + * @param {number[]} data + * @param {number[]} shape + */ + +export function checkShape(data, shape) { + if (data.length && shape.length && data.length !== shape.reduce((a, b) => a * b, 1)) { + throw new Error('[Tensor] specified shape incompatible with data.') + } +} + +/** + * Shuffle ndarray data layout for WebGL + * - data for TEXTURE_2D_ARRAY or TEXTURE_3D laid out sequentially per-slice + * + * @param {TypedArray} typedarrayConstructor + * @param {Object} arr - ndarray tensor + * @param {number[]} shape + */ +export function data3DLayoutForGL(typedarrayConstructor, arr, shape) { + const data = new typedarrayConstructor(arr.data.length) + const slice = ndarray(new typedarrayConstructor(shape[0] * shape[1]), [shape[0], shape[1]]) + let offset = 0 + for (let i = 0; i < shape[2]; i++) { + ops.assign(slice, arr.pick(null, null, i)) + data.set(slice.data, offset) + offset += shape[0] * shape[1] + } + + return data +} + +/** + * Create indicesForReshaped for 2D reshaped tensor + * + * @param {number[]} shape + * @param {boolean} square + * @param {number} axis + */ +export function createIndicesFor2DReshaped(shape, square = false, axis = -1) { + const size = shape.reduce((a, b) => a * b, 1) + const indicesArr = ndarray(new Int32Array(size), shape) + + if (square) { + // called by Tensor.reshapeTo2DSquare + const squareDim = Math.ceil(Math.sqrt(size)) + const indicesRowArrReshaped = ndarray(new Int32Array(squareDim ** 2), [squareDim, squareDim]) + const indicesColArrReshaped = ndarray(new Int32Array(squareDim ** 2), [squareDim, squareDim]) + const indicesArrReshaped = ndarray(new Int32Array(squareDim ** 2), [squareDim, squareDim]) + for (let i = 0; i < squareDim; i++) { + ops.assigns(indicesRowArrReshaped.pick(i, null), i) + } + for (let j = 0; j < squareDim; j++) { + ops.assigns(indicesColArrReshaped.pick(null, j), j) + } + // i * cols + j + ops.muls(indicesArrReshaped, indicesRowArrReshaped, squareDim) + ops.addeq(indicesArrReshaped, indicesColArrReshaped) + indicesArr.data.set(indicesArrReshaped.data.subarray(0, indicesArr.size)) + } else { + // called by Tensor.reshapeTo2D + if (axis < 0) { + axis = shape.length + axis + } + const axisSize = shape[axis] + const indicesRowArr = ndarray(new Int32Array(size), shape) + const indicesColArr = ndarray(new Int32Array(size), shape) + const otherAxes = [...shape.slice(0, axis), ...shape.slice(axis + 1)] + const otherAxesSize = otherAxes.reduce((a, b) => a * b, 1) + const indicesRowArrSlice = ndarray(new Int32Array(_.range(otherAxesSize)), otherAxes) + const axisSlices = Array(shape.length).fill(null) + for (let n = 0; n < axisSize; n++) { + axisSlices[axis] = n + ops.assign(indicesRowArr.pick(...axisSlices), indicesRowArrSlice) + ops.assigns(indicesColArr.pick(...axisSlices), n) + } + // i * cols + j + ops.muls(indicesArr, indicesRowArr, axisSize) + ops.addeq(indicesArr, indicesColArr) + } + + return indicesArr +} diff --git a/keras-js/src/utils/testUtils.js b/keras-js/src/utils/testUtils.js new file mode 100644 index 0000000000..8e67fc2668 --- /dev/null +++ b/keras-js/src/utils/testUtils.js @@ -0,0 +1,29 @@ +import unpack from 'ndarray-unpack' +import _ from 'lodash' + +/** + * Compares an ndarray's data element-wise to dataExpected, + * within a certain tolerance. We unpack the ndarray first since + * stride/offset prevents us from comparing the array data + * element-wise directly. + * + * @param {Object} ndarrayOut + * @param {number[]} dataExpected + * @param {number} tol + */ +export function approxEquals(ndarrayOut, dataExpected, tol = 0.0001) { + const a = _.flattenDeep(unpack(ndarrayOut)) + const b = dataExpected + if (a.length !== b.length) { + return false + } + for (let i = 0; i < a.length; i++) { + if (!_.isFinite(a[i])) { + return false + } + if (a[i] < b[i] - tol || a[i] > b[i] + tol) { + return false + } + } + return true +} diff --git a/keras-js/src/visualizations/CAM.js b/keras-js/src/visualizations/CAM.js new file mode 100644 index 0000000000..5a3f9e5cb6 --- /dev/null +++ b/keras-js/src/visualizations/CAM.js @@ -0,0 +1,154 @@ +import Tensor from '../Tensor' +import { webgl2 } from '../WebGL2' +import ops from 'ndarray-ops' +import { gemv } from 'ndarray-blas-level2' +import gemm from 'ndarray-gemm' +import createGLSLProgram from '../webgl/dynamic/createGLSLProgram' + +/** + * Class Activation Maps + */ +export default class CAM { + /** + * @param {Object} [attrs] - visualization layer attributes + */ + constructor(attrs = {}) { + this.modelLayersMap = attrs.modelLayersMap + this.gpu = attrs.gpu + + if (!this.modelLayersMap) { + throw new Error(`[CAM] modelLayersMap is required`) + } + } + + /** + * Checks whether CAM can be computed directly (requires GlobalAveragePooling2D layer) + * Grad-CAM generalizes this to arbitrary architectures, and may be implemented in the future. + */ + initialize() { + this.modelLayersMap.forEach(layer => { + if (layer.layerClass === 'GlobalAveragePooling2D') { + this.enabled = true + this.poolLayer = layer + } + }) + + if (this.enabled && !this.data) { + // get feature maps from preceding layer + this.featureMaps = this.modelLayersMap.get(this.poolLayer.inbound[0]).output + + // traverse until we get feature map weights + // in Inception-V3, for example, this is the kernel weights of the final fully-connected layer + // in Squeezenet, for example, this is simply the output of the GlobalAveragePooling2D layer + let weightsFound = false + let finalLayerReached = false + let traversingLayer = this.poolLayer + while (!weightsFound && !finalLayerReached) { + traversingLayer = this.modelLayersMap.get(traversingLayer.outbound[0]) + if (traversingLayer.weights['kernel']) { + this.weights = traversingLayer.weights['kernel'] + weightsFound = true + } else if (!traversingLayer.outbound.length) { + this.weights = this.poolLayer.output + finalLayerReached = true + } + } + + if (this.featureMaps.is2DReshaped) { + this.inputShape = this.featureMaps.originalShape.slice(0, 2) + } else { + this.inputShape = this.featureMaps.tensor.shape.slice(0, 2) + } + if (this.weights.tensor.shape.length === 1) { + this.shape = this.inputShape + } else { + const numOutputClasses = this.weights.tensor.shape[1] + this.shape = [...this.inputShape, numOutputClasses] + } + this.data = new Float32Array(this.shape.reduce((a, b) => a * b, 1)) + } + } + + /** + * Update visualization output + */ + update() { + if (!this.enabled) return + + // get feature maps from preceding layer + this.featureMaps = this.modelLayersMap.get(this.poolLayer.inbound[0]).output + + if (this.gpu) { + this._updateGPU() + } else { + this._updateCPU() + } + + // normalize 0-1 + const outputMin = ops.inf(this.output.tensor) + const outputMax = ops.sup(this.output.tensor) + ops.divseq(ops.subseq(this.output.tensor, outputMin), outputMax - outputMin) + + // update data + this.data = this.output.tensor.data + } + + _updateCPU() { + if (!this.featureMaps.is2DReshaped) { + this.featureMaps.reshapeTo2D() + } + + if (this.weights.tensor.shape.length === 1) { + if (!this.output) { + this.output = new Tensor([], this.shape) + } + const matVec = new Tensor([], [this.shape[0] * this.shape[1]]) + gemv(1, this.featureMaps.tensor, this.weights.tensor, 1, matVec.tensor) + this.output.replaceTensorData(matVec.tensor.data) + } else { + if (!this.output) { + this.output = new Tensor([], this.shape) + } + this.output.reshapeTo2D() + gemm(this.output.tensor, this.featureMaps.tensor, this.weights.tensor, 1, 1) + this.output.reshapeFrom2D() + } + ops.maxseq(this.output.tensor, 0) + + if (this.featureMaps.is2DReshaped) { + this.featureMaps.reshapeFrom2D() + } + } + + _updateGPU() { + if (!this.output) { + this.output = new Tensor([], this.shape) + } + + const isWeights1D = this.weights.is1D + + if (!this.output.glTexture && isWeights1D) { + this.output.createGLTexture({ type: '2d', format: 'float' }) + } else { + this.output.reshapeTo2D() + this.output.createGLTexture({ type: '2d', format: 'float' }) + } + + const numFeatures = isWeights1D ? this.weights.glTextureShape[1] : this.weights.glTextureShape[0] + if (!this.program) { + const programSource = createGLSLProgram('cam', this.output.glTextureShape, numFeatures, isWeights1D) + this.program = webgl2.compileProgram(programSource) + } + webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ input: this.featureMaps, name: 'featureMaps' }, { input: this.weights, name: 'weights' }] + }) + + // GPU -> CPU data transfer + this.output.transferFromGLTexture() + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D() + } + } +} diff --git a/keras-js/src/visualizations/index.js b/keras-js/src/visualizations/index.js new file mode 100644 index 0000000000..e3be7edcff --- /dev/null +++ b/keras-js/src/visualizations/index.js @@ -0,0 +1,3 @@ +import CAM from './CAM' + +export { CAM } diff --git a/keras-js/src/webgl/copyTexture.glsl b/keras-js/src/webgl/copyTexture.glsl new file mode 100644 index 0000000000..604cafe416 --- /dev/null +++ b/keras-js/src/webgl/copyTexture.glsl @@ -0,0 +1,10 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D source; +out vec4 outColor; + +void main(void) { + outColor = texture(source, vec2(outTex.x, outTex.y)); +} diff --git a/keras-js/src/webgl/dynamic/convolutional/conv2d.js b/keras-js/src/webgl/dynamic/convolutional/conv2d.js new file mode 100644 index 0000000000..0ef5f141c8 --- /dev/null +++ b/keras-js/src/webgl/dynamic/convolutional/conv2d.js @@ -0,0 +1,51 @@ +/** + * Create GLSL program for convolutional.Conv2D layer + * + * @param {number[]} outputShape + * @param {number[]} inputShape + * @param {number[]} indexMapShape + * @param {boolean} useBias + * @param {boolean} [hasFragments] + */ +export default function conv2d(outputShape, inputShape, indexMapShape, useBias, hasFragments) { + const addBias = useBias ? `sum += texelFetch(bias, ivec2(out_x, 0), 0).r;` : '' + + const adjustIndicesForFragments = hasFragments + ? `int fragmentIndex = int(floor(float(rowIndex) / float(${inputShape[0]}))); + rowIndex = int(mod(float(rowIndex), float(${inputShape[0]}))); + colIndex += fragmentIndex * ${inputShape[1]};` + : '' + + const source = `#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D x; +uniform isampler2D indexMap; +uniform sampler2D kernel; +uniform sampler2D bias; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int i = 0; i < ${indexMapShape[1]}; ++i) { + int index = texelFetch(indexMap, ivec2(i, out_y), 0).r; + if (index != -1) { + int rowIndex = int(floor(float(index) / float(${inputShape[1]}))); + int colIndex = int(mod(float(index), float(${inputShape[1]}))); + ${adjustIndicesForFragments} + sum += texelFetch(x, ivec2(colIndex, rowIndex), 0).r * texelFetch(kernel, ivec2(out_x, i), 0).r; + } + } + + ${addBias} + outColor = vec4(sum); +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/convolutional/conv2dTranspose.js b/keras-js/src/webgl/dynamic/convolutional/conv2dTranspose.js new file mode 100644 index 0000000000..c876bee610 --- /dev/null +++ b/keras-js/src/webgl/dynamic/convolutional/conv2dTranspose.js @@ -0,0 +1,50 @@ +/** + * Create GLSL program for convolutional.Conv2DTranspose layer + * + * @param {number[]} outputShape + * @param {number[]} inputShape + * @param {number[]} indexMapShape + * @param {boolean} useBias + * @param {boolean} [hasFragments] + */ +export default function conv2dTranspose(outputShape, inputShape, indexMapShape, useBias, hasFragments) { + const addBias = useBias ? `sum += texelFetch(bias, ivec2(out_x, 0), 0).r;` : '' + + const adjustIndicesForFragments = hasFragments + ? `int fragmentIndex = int(floor(float(rowIndex) / float(${inputShape[0]}))); + rowIndex = int(mod(float(rowIndex), float(${inputShape[0]}))); + colIndex += fragmentIndex * ${inputShape[1]};` + : '' + + const source = `#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D matMulResult; +uniform isampler2D indexMap; +uniform sampler2D bias; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int n = 0; n < ${indexMapShape[1]}; ++n) { + int index = texelFetch(indexMap, ivec2(n, out_y), 0).r; + if (index != -1) { + int rowIndex = int(floor(float(index) / float(${inputShape[1]}))); + int colIndex = int(mod(float(index), float(${inputShape[1]}))); + ${adjustIndicesForFragments} + sum += texelFetch(matMulResult, ivec2(colIndex + out_x, rowIndex), 0).r; + } + } + + ${addBias} + outColor = vec4(sum); +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/createGLSLProgram.js b/keras-js/src/webgl/dynamic/createGLSLProgram.js new file mode 100644 index 0000000000..892fb7387b --- /dev/null +++ b/keras-js/src/webgl/dynamic/createGLSLProgram.js @@ -0,0 +1,43 @@ +import add from './merge/add' +import average from './merge/average' +import concatenate from './merge/concatenate' +import maximum from './merge/maximum' +import minimum from './merge/minimum' +import multiply from './merge/multiply' +import subtract from './merge/subtract' +import conv2d from './convolutional/conv2d' +import conv2dTranspose from './convolutional/conv2dTranspose' +import cam from './visualizations/cam' + +export default function createGLSLProgram(program, ...args) { + switch (program) { + // merge + case 'add': + return add(...args) + case 'average': + return average(...args) + case 'concatenate': + return concatenate(...args) + case 'maximum': + return maximum(...args) + case 'minimum': + return minimum(...args) + case 'multiply': + return multiply(...args) + case 'subtract': + return subtract(...args) + + // convolutional + case 'conv2d': + return conv2d(...args) + case 'conv2dTranspose': + return conv2dTranspose(...args) + + // visualizations + case 'cam': + return cam(...args) + + default: + throw new Error('GLSL program not found') + } +} diff --git a/keras-js/src/webgl/dynamic/merge/add.js b/keras-js/src/webgl/dynamic/merge/add.js new file mode 100644 index 0000000000..bac8b5ccf2 --- /dev/null +++ b/keras-js/src/webgl/dynamic/merge/add.js @@ -0,0 +1,28 @@ +import _ from 'lodash' + +/** + * Create GLSL program for merge.Add layer + * + * @param {number} numInputs + * @param {number[]} shape + */ +export default function add(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(${_.range(numInputs) + .map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`) + .join(' + ')}); +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/merge/average.js b/keras-js/src/webgl/dynamic/merge/average.js new file mode 100644 index 0000000000..09632cf225 --- /dev/null +++ b/keras-js/src/webgl/dynamic/merge/average.js @@ -0,0 +1,28 @@ +import _ from 'lodash' + +/** + * Create GLSL program for merge.Average layer + * + * @param {number} numInputs + * @param {number[]} shape + */ +export default function average(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4((${_.range(numInputs) + .map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`) + .join(' + ')}) / float(${numInputs})); +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/merge/concatenate.js b/keras-js/src/webgl/dynamic/merge/concatenate.js new file mode 100644 index 0000000000..eb8ef913c3 --- /dev/null +++ b/keras-js/src/webgl/dynamic/merge/concatenate.js @@ -0,0 +1,63 @@ +import _ from 'lodash' + +/** + * Create GLSL program for merge.Concatenate layer + * + * @param {number} numInputs + * @param {number[][]} inputShapes + * @param {number[]} outputShape + * @param {number} concatAxis + */ +export default function concatenate(numInputs, inputShapes, outputShape, concatAxis) { + const dims = inputShapes.map(shape => shape[concatAxis]) + const offsets = _.range(numInputs + 1).map(i => _.sum(_.take(dims, i))) + + const outVar = concatAxis === 0 ? 'out_y' : 'out_x' + let getOffset = ` + int n = 0; + int offset = 0; + if (${outVar} >= ${offsets[1]} && ${outVar} < ${offsets[2]}) { + n = 1; + offset = ${offsets[1]}; + }` + if (numInputs > 2) { + // prettier-ignore + getOffset += `${_.range(2, numInputs).map(i => + ` else if (${outVar} >= ${offsets[i]} && ${outVar} < ${offsets[i + 1]}) { + n = ${i}; + offset = ${offsets[i]}; + }`).join('')} +` + } + + let outBlock = 'outColor = vec4(0.0);' + if (concatAxis === 0 || concatAxis === 1) { + const xCoord = i => `out_x${concatAxis === 1 ? ` - ${offsets[i]}` : ''}` + const yCoord = i => `out_y${concatAxis === 0 ? ` - ${offsets[i]}` : ''}` + // prettier-ignore + outBlock = ` + if (n == 0) { + outColor = vec4(texelFetch(inputs[0], ivec2(out_x, out_y), 0).r); + }${_.range(1, numInputs).map(i => ` else if (n == ${i}) { + outColor = vec4(texelFetch(inputs[${i}], ivec2(${xCoord(i)}, ${yCoord(i)}), 0).r); + }`).join('')} +` + } + + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); +${getOffset} +${outBlock} +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/merge/maximum.js b/keras-js/src/webgl/dynamic/merge/maximum.js new file mode 100644 index 0000000000..fdc84a6533 --- /dev/null +++ b/keras-js/src/webgl/dynamic/merge/maximum.js @@ -0,0 +1,29 @@ +/** + * Create GLSL program for merge.Maximum layer + * + * @param {number} numInputs + * @param {number[]} shape + */ +export default function maximum(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + float val = texelFetch(inputs[0], ivec2(out_x, out_y), 0).r; + for (int i = 1; i < ${numInputs}; i++) { + val = max(val, texelFetch(inputs[i], ivec2(out_x, out_y), 0).r); + } + + outColor = vec4(val); +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/merge/minimum.js b/keras-js/src/webgl/dynamic/merge/minimum.js new file mode 100644 index 0000000000..16ce2cd9b7 --- /dev/null +++ b/keras-js/src/webgl/dynamic/merge/minimum.js @@ -0,0 +1,29 @@ +/** + * Create GLSL program for merge.Minimum layer + * + * @param {number} numInputs + * @param {number[]} shape + */ +export default function minimum(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + float val = texelFetch(inputs[0], ivec2(out_x, out_y), 0).r; + for (int i = 1; i < ${numInputs}; i++) { + val = min(val, texelFetch(inputs[i], ivec2(out_x, out_y), 0).r); + } + + outColor = vec4(val); +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/merge/multiply.js b/keras-js/src/webgl/dynamic/merge/multiply.js new file mode 100644 index 0000000000..56ddd9b2ec --- /dev/null +++ b/keras-js/src/webgl/dynamic/merge/multiply.js @@ -0,0 +1,28 @@ +import _ from 'lodash' + +/** + * Create GLSL program for merge.Multiply layer + * + * @param {number} numInputs + * @param {number[]} shape + */ +export default function multiply(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(${_.range(numInputs) + .map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`) + .join(' * ')}); +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/merge/subtract.js b/keras-js/src/webgl/dynamic/merge/subtract.js new file mode 100644 index 0000000000..e14fd3ba04 --- /dev/null +++ b/keras-js/src/webgl/dynamic/merge/subtract.js @@ -0,0 +1,24 @@ +/** + * Create GLSL program for merge.Subtract layer + * + * @param {number} numInputs + * @param {number[]} shape + */ +export default function subtract(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[2]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(texelFetch(inputs[0], ivec2(out_x, out_y), 0).r - texelFetch(inputs[1], ivec2(out_x, out_y), 0).r); +} +` + + return source +} diff --git a/keras-js/src/webgl/dynamic/visualizations/cam.js b/keras-js/src/webgl/dynamic/visualizations/cam.js new file mode 100644 index 0000000000..953401240a --- /dev/null +++ b/keras-js/src/webgl/dynamic/visualizations/cam.js @@ -0,0 +1,70 @@ +/** + * Create GLSL program for CAM visualization + * + * @param {number[]} outputShape + * @param {number} numFeatures + * @param {boolean} weightsIs1D + */ +export default function cam(outputShape, numFeatures, weightsIs1D) { + let source + + if (weightsIs1D) { + // we calculate the activation map directly + // output shape will be [height, width] + // only non-negative activation passes through + + source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D featureMaps; +uniform sampler2D weights; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + int featureMapsRow = out_x + ${outputShape[0]} * out_y; + + float sum = 0.; + for (int k = 0; k < ${numFeatures}; ++k) { + float f = texelFetch(featureMaps, ivec2(k, featureMapsRow), 0).r; + float w = texelFetch(weights, ivec2(k, 0), 0).r; + sum += f * w; + } + + outColor = vec4(max(sum, 0.0)); +} +` + } else { + // we calculate the activation map on the reshaped features + // output shape will be [height * width, numClasses] + // only non-negative activation passes through + + source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D featureMaps; +uniform sampler2D weights; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int k = 0; k < ${numFeatures}; ++k) { + float f = texelFetch(featureMaps, ivec2(k, out_y), 0).r; + float w = texelFetch(weights, ivec2(out_x, k), 0).r; + sum += f * w; + } + + outColor = vec4(max(sum, 0.0)); +} +` + } + + return source +} diff --git a/keras-js/src/webgl/mapInput.fragments.glsl b/keras-js/src/webgl/mapInput.fragments.glsl new file mode 100644 index 0000000000..bd24a2ba49 --- /dev/null +++ b/keras-js/src/webgl/mapInput.fragments.glsl @@ -0,0 +1,30 @@ +#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D x; +uniform isampler2D indexMap; +uniform int inputCols; +out vec4 outColor; + +void main() { + ivec2 inputSize = textureSize(x, 0); + ivec2 outputSize = textureSize(indexMap, 0); + int out_x = int(float(outputSize[0]) * outTex.x); + int out_y = int(float(outputSize[1]) * outTex.y); + + int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r; + + if (index != -1) { + int rowIndex = int(floor(float(index) / float(inputCols))); + int colIndex = int(mod(float(index), float(inputCols))); + int fragmentIndex = int(floor(float(rowIndex) / float(inputSize[1]))); + rowIndex = int(mod(float(rowIndex), float(inputSize[1]))); + colIndex = fragmentIndex * inputCols + colIndex; + float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r; + outColor = vec4(val); + } else { + outColor = vec4(0.0); + } +} diff --git a/keras-js/src/webgl/mapInput.glsl b/keras-js/src/webgl/mapInput.glsl new file mode 100644 index 0000000000..9231e20bb5 --- /dev/null +++ b/keras-js/src/webgl/mapInput.glsl @@ -0,0 +1,26 @@ +#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D x; +uniform isampler2D indexMap; +uniform int inputCols; +out vec4 outColor; + +void main() { + ivec2 size = textureSize(indexMap, 0); + int out_x = int(float(size[0]) * outTex.x); + int out_y = int(float(size[1]) * outTex.y); + + int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r; + + if (index != -1) { + int rowIndex = int(floor(float(index) / float(inputCols))); + int colIndex = int(mod(float(index), float(inputCols))); + float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r; + outColor = vec4(val); + } else { + outColor = vec4(0.0); + } +} diff --git a/keras-js/src/webgl/matMul.glsl b/keras-js/src/webgl/matMul.glsl new file mode 100644 index 0000000000..1875a27f72 --- /dev/null +++ b/keras-js/src/webgl/matMul.glsl @@ -0,0 +1,30 @@ +#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D A; +uniform sampler2D B; +uniform sampler2D C; +uniform bool addC; +out vec4 outColor; + +void main() { + ivec2 A_size = textureSize(A, 0); + ivec2 B_size = textureSize(B, 0); + int out_x = int(float(B_size[0]) * outTex.x); + int out_y = int(float(A_size[1]) * outTex.y); + int commonDim = A_size[0]; + + float sum = 0.; + for (int i = 0; i < commonDim; ++i) { + float a = texelFetch(A, ivec2(i, out_y), 0).r; + float b = texelFetch(B, ivec2(out_x, i), 0).r; + sum += a * b; + } + + if (addC) { + sum += texelFetch(C, ivec2(out_x, 0), 0).r; + } + + outColor = vec4(sum); +} diff --git a/keras-js/src/webgl/vertexShader.glsl b/keras-js/src/webgl/vertexShader.glsl new file mode 100644 index 0000000000..17c7d0e5dd --- /dev/null +++ b/keras-js/src/webgl/vertexShader.glsl @@ -0,0 +1,11 @@ +#version 300 es +precision highp float; + +in vec3 position; +in vec2 texcoord; +out vec2 outTex; + +void main () { + gl_Position = vec4(position, 1.0); + outTex = texcoord; +} diff --git a/keras-js/webpack.config.js b/keras-js/webpack.config.js new file mode 100644 index 0000000000..f2e0e5af8a --- /dev/null +++ b/keras-js/webpack.config.js @@ -0,0 +1,15 @@ +const path = require('path') + +const config = { + entry: path.resolve(__dirname, 'src/index'), + resolve: { extensions: ['.js'] }, + output: { path: path.resolve(__dirname, 'dist'), filename: 'keras.min.js', library: 'KerasJS', libraryTarget: 'umd' }, + module: { + rules: [{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }] + }, + node: { + fs: 'empty' + } +} + +module.exports = config diff --git a/lib/Layer.js b/lib/Layer.js new file mode 100644 index 0000000000..e218b0e2b3 --- /dev/null +++ b/lib/Layer.js @@ -0,0 +1,55 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _WebGL = require("./WebGL2"); + +class Layer { + constructor(attrs = {}) { + this.layerClass = 'Layer'; + this.name = attrs.name; + this.gpu = _WebGL.webgl2.isSupported && attrs.gpu; + this.params = []; + this.weights = {}; + this.inbound = []; + this.outbound = []; + } + + throwError(message) { + throw new Error(`[${this.layerClass} layer: ${this.name || ''}] ${message}`); + } + + toggleGPU(mode) { + const newMode = typeof mode === 'undefined' ? !this.gpu : mode; + + if (_WebGL.webgl2.isSupported && newMode) { + this.gpu = true; + } else { + this.gpu = false; + } + } + + setWeights(weightsArr, createGLTexture = true) { + this.params.forEach((p, i) => { + this.weights[p] = weightsArr[i]; + + if (this.gpu && createGLTexture) { + this.weights[p].createGLTexture({ + type: '2d', + format: 'float' + }); + } + }); + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = Layer; \ No newline at end of file diff --git a/lib/Model.js b/lib/Model.js new file mode 100644 index 0000000000..584f591920 --- /dev/null +++ b/lib/Model.js @@ -0,0 +1,493 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _keys2 = _interopRequireDefault(require("lodash/keys")); + +var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); + +var _map2 = _interopRequireDefault(require("lodash/map")); + +var _every2 = _interopRequireDefault(require("lodash/every")); + +var _find2 = _interopRequireDefault(require("lodash/find")); + +var _bluebird = _interopRequireDefault(require("bluebird")); + +var _axios = _interopRequireDefault(require("axios")); + +var _performanceNow = _interopRequireDefault(require("performance-now")); + +var layers = _interopRequireWildcard(require("./layers")); + +var visMethods = _interopRequireWildcard(require("./visualizations")); + +var _Tensor = _interopRequireDefault(require("./Tensor")); + +var _WebGL = require("./WebGL2"); + +var _proto = _interopRequireDefault(require("./proto")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const axiosSource = _axios.default.CancelToken.source(); + +class Model { + constructor(config = {}) { + const { + filepath = null, + headers = {}, + filesystem = false, + gpu = false, + transferLayerOutputs = false, + pauseAfterLayerCalls = false, + visualizations = [] + } = config; + + if (!filepath) { + throw new Error('[Model] path to protobuf-serialized model definition file is missing.'); + } + + this.filepath = filepath; + this.headers = headers; + this.filesystem = typeof window !== 'undefined' ? false : filesystem; + this.dataRequestProgress = 0; + this.id = null; + this.name = null; + this.kerasVersion = null; + this.backend = null; + this.modelConfig = {}; + this.modelWeights = []; + this.gpu = typeof window !== 'undefined' && _WebGL.webgl2.isSupported ? gpu : false; + this.transferLayerOutputs = transferLayerOutputs; + this.pauseAfterLayerCalls = pauseAfterLayerCalls; + this.modelLayersMap = new Map(); + this.inputTensorsMap = new Map(); + this.inputLayerNames = []; + this.outputLayerNames = []; + this.finishedLayerNames = []; + this.isRunning = false; + this.predictStats = {}; + this.visMap = new Map(); + visualizations.forEach(v => { + if (v in visMethods) { + const visInstance = new visMethods[v]({ + modelLayersMap: this.modelLayersMap, + gpu: this.gpu + }); + this.visMap.set(v, visInstance); + } + }); + this._ready = this._initialize(); + } + + checkGPUSupport() { + return _WebGL.webgl2.isSupported; + } + + ready() { + return this._ready; + } + + _interrupt() { + axiosSource.cancel(); + } + + async _initialize() { + try { + const req = this.filesystem ? this._dataRequestFS() : this._dataRequestHTTP(this.headers); + await req; + } catch (err) { + console.log(err); + + this._interrupt(); + } + + this._buildDAG(); + + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name); + inputLayer.call(this.inputTensorsMap.get(name)); + inputLayer.hasOutput = true; + inputLayer.visited = true; + }); + await this._traverseDAG(this.inputLayerNames); + this.finishedLayerNames = []; + this.modelLayersMap.forEach(layer => { + layer.hasOutput = false; + layer.visited = false; + }); + this.visMap.forEach(visInstance => { + visInstance.initialize(); + }); + return true; + } + + async _dataRequestHTTP(headers = {}) { + try { + const res = await _axios.default.get(this.filepath, { + responseType: 'arraybuffer', + headers, + onDownloadProgress: e => { + if (e.lengthComputable) { + const percentComplete = Math.round(100 * e.loaded / e.total); + this.dataRequestProgress = percentComplete; + } + }, + cancelToken: axiosSource.token + }); + this.decodeProtobuf(new Uint8Array(res.data)); + } catch (err) { + if (_axios.default.isCancel(err)) { + console.log('[Model] Data request canceled', err.message); + } else { + throw err; + } + } + + this.dataRequestProgress = 100; + } + + async _dataRequestFS() { + const readFile = _bluebird.default.promisify(require('fs').readFile); + + try { + const file = await readFile(this.filepath); + this.decodeProtobuf(file); + } catch (err) { + throw err; + } + + this.dataRequestProgress = 100; + } + + decodeProtobuf(buffer) { + const err = _proto.default.Model.verify(buffer); + + if (err) { + throw new Error(`[Model] Invalid model - check protobuf serialization: {err}`); + } + + const model = _proto.default.Model.decode(buffer); + + this.id = model.id; + this.name = model.name; + this.kerasVersion = model.kerasVersion; + this.backend = model.backend; + this.modelConfig = JSON.parse(model.modelConfig); + this.modelWeights = model.modelWeights; + } + + getLoadingProgress() { + return this.dataRequestProgress; + } + + toggleGPU(mode) { + if (typeof mode === 'undefined') { + this.gpu = !this.gpu; + } else { + this.gpu = mode; + } + + this.modelLayersMap.forEach(layer => { + layer.toggleGPU(this.gpu); + }); + this.visMap.forEach(visInstance => { + visInstance.gpu = this.gpu; + }); + this.resetInputTensors(); + } + + resetInputTensors() { + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name); + this.inputTensorsMap.set(name, new _Tensor.default([], inputLayer.shape)); + }); + } + + _buildDAG() { + const modelClass = this.modelConfig.class_name; + let modelConfig = []; + + if (modelClass === 'Sequential') { + modelConfig = this.modelConfig.config; + } else if (modelClass === 'Model') { + modelConfig = this.modelConfig.config.layers; + } + + if (!(Array.isArray(modelConfig) && modelConfig.length)) { + throw new Error('[Model] Model configuration does not contain any layers.'); + } + + modelConfig.forEach((layerDef, index) => { + const layerClass = layerDef.class_name; + const layerConfig = layerDef.config; + + if (modelClass === 'Model' && layerClass === 'Sequential') { + layerConfig.forEach((branchLayerDef, branchIndex) => { + const branchLayerClass = branchLayerDef.class_name; + const branchLayerConfig = branchLayerDef.config; + const branchInboundLayerNames = branchIndex === 0 ? layerDef.inbound_nodes[0].map(node => node[0]) : [layerConfig[branchIndex - 1].config.name]; + + this._createLayer(branchLayerClass, branchLayerConfig, branchInboundLayerNames); + }); + } else if (!(layerClass in layers)) { + throw new Error(`[Model] Layer ${layerClass} specified in model configuration is not implemented!`); + } else { + if (modelClass === 'Sequential' && index === 0) { + const inputName = 'input'; + const inputShape = layerConfig.batch_input_shape.slice(1); + const layer = new layers.InputLayer({ + name: inputName, + shape: inputShape, + gpu: this.gpu + }); + this.modelLayersMap.set(inputName, layer); + this.inputTensorsMap.set(inputName, new _Tensor.default([], inputShape)); + this.inputLayerNames.push(inputName); + } else if (modelClass === 'Model' && layerClass === 'InputLayer') { + const inputShape = layerConfig.batch_input_shape.slice(1); + this.inputTensorsMap.set(layerConfig.name, new _Tensor.default([], inputShape)); + this.inputLayerNames.push(layerConfig.name); + } + + let inboundLayerNames = []; + + if (modelClass === 'Sequential') { + if (index === 0) { + inboundLayerNames = ['input']; + } else { + inboundLayerNames = [modelConfig[index - 1].config.name]; + } + } else if (modelClass === 'Model') { + const inboundNodes = layerDef.inbound_nodes; + + if (inboundNodes && inboundNodes.length) { + inboundLayerNames = inboundNodes[0].map(node => node[0]); + } + } + + this._createLayer(layerClass, layerConfig, inboundLayerNames); + } + }); + this.modelLayersMap.forEach(layer => { + if (layer.outbound.length === 0) { + this.outputLayerNames.push(layer.name); + } + }); + this.inputLayerNames.sort(); + this.outputLayerNames.sort(); + } + + _createLayer(layerClass, layerConfig, inboundLayerNames) { + const layer = new layers[layerClass](Object.assign({}, layerConfig, { + gpu: this.gpu + })); + let weightNames = []; + + if (layerClass === 'Bidirectional') { + const forwardWeightNames = layer.forwardLayer.params.map(param => `${layerConfig.name}/forward_${layerConfig.layer.config.name}/${param}`); + const backwardWeightNames = layer.backwardLayer.params.map(param => `${layerConfig.name}/backward_${layerConfig.layer.config.name}/${param}`); + weightNames = forwardWeightNames.concat(backwardWeightNames); + } else if (layerClass === 'TimeDistributed') { + weightNames = layer.layer.params.map(param => `${layerConfig.name}/${param}`); + } else { + weightNames = layer.params.map(param => `${layerConfig.name}/${param}`); + } + + if (weightNames && weightNames.length) { + const weights = weightNames.map(weightName => { + const weightDef = (0, _find2.default)(this.modelWeights, w => { + const weightRE = new RegExp(`^${weightName}`); + return weightRE.test(w.weightName); + }); + + if (!weightDef) { + throw new Error(`[Model] error loading weights.`); + } + + const { + data, + shape, + type + } = weightDef; + const buf = new ArrayBuffer(data.byteLength); + const arr = new Uint8Array(buf); + arr.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); + + if (type === 'uint8') { + const { + quantizeMin, + quantizeMax + } = weightDef; + const unquantized = new Float32Array(arr); + + for (let i = 0, len = unquantized.length; i < len; i++) { + unquantized[i] *= (quantizeMax - quantizeMin) / 255; + unquantized[i] += quantizeMin; + } + + return new _Tensor.default(unquantized, shape); + } else { + return new _Tensor.default(new Float32Array(buf), shape); + } + }); + layer.setWeights(weights); + } + + this.modelLayersMap.set(layerConfig.name, layer); + inboundLayerNames.forEach(layerName => { + this.modelLayersMap.get(layerConfig.name).inbound.push(layerName); + this.modelLayersMap.get(layerName).outbound.push(layerConfig.name); + }); + } + + async _traverseDAG(nodes) { + if (nodes.length === 0) { + return true; + } else if (nodes.length === 1) { + const node = nodes[0]; + const currentLayer = this.modelLayersMap.get(node); + + if (currentLayer.layerClass === 'InputLayer') { + this.finishedLayerNames.push(this.modelLayersMap.get(node).name); + } else { + const currentLayer = this.modelLayersMap.get(node); + + if (currentLayer.visited) { + return false; + } + + const inboundLayers = currentLayer.inbound.map(n => this.modelLayersMap.get(n)); + + if (!(0, _every2.default)((0, _map2.default)(inboundLayers, 'hasOutput'))) { + return false; + } + + if (currentLayer.isMergeLayer) { + currentLayer.call((0, _map2.default)(inboundLayers, 'output')); + } else { + currentLayer.call(inboundLayers[0].output); + } + + currentLayer.hasOutput = true; + currentLayer.visited = true; + this.finishedLayerNames.push(currentLayer.name); + + if (this.pauseAfterLayerCalls) { + await _bluebird.default.delay(0); + } + } + + await this._traverseDAG(currentLayer.outbound); + } else { + await _bluebird.default.all(nodes.map(node => this._traverseDAG([node]))); + } + } + + _maybeTransferIntermediateOutputs() { + if (this.gpu && this.transferLayerOutputs) { + this.modelLayersMap.forEach(layer => { + if (layer.output && layer.output.glTexture) { + _WebGL.webgl2.bindOutputTexture(layer.output.glTexture, layer.output.glTextureShape); + + layer.output.transferFromGLTexture(); + + if (layer.output.is2DReshaped) { + layer.output.reshapeFrom2D(); + } + } + }); + } + } + + loadData(inputData) { + this.inputLayerNames.forEach(name => { + const inputLayer = this.modelLayersMap.get(name); + this.inputTensorsMap.get(name).replaceTensorData(inputData[name]); + inputLayer.call(this.inputTensorsMap.get(name)); + inputLayer.hasOutput = true; + inputLayer.visited = true; + }); + } + + async predict(inputData) { + this.isRunning = true; + + if (!(0, _isEqual2.default)((0, _keys2.default)(inputData).sort(), this.inputLayerNames)) { + this.isRunning = false; + throw new Error('[Model] predict() must take an object where the keys are the named inputs of the model: ' + JSON.stringify(this.inputLayerNames)); + } + + if (!(0, _every2.default)(this.inputLayerNames, name => inputData[name] instanceof Float32Array)) { + this.isRunning = false; + throw new Error('[Model] predict() must take an object where the values are the flattened data as Float32Array.'); + } + + this.finishedLayerNames = []; + this.modelLayersMap.forEach(layer => { + layer.hasOutput = false; + layer.visited = false; + }); + let start = (0, _performanceNow.default)(); + this.loadData(inputData); + this.predictStats.loadData = (0, _performanceNow.default)() - start; + start = (0, _performanceNow.default)(); + await this._traverseDAG(this.inputLayerNames); + this.predictStats.forwardPass = (0, _performanceNow.default)() - start; + + this._maybeTransferIntermediateOutputs(); + + const modelClass = this.modelConfig.class_name; + const outputData = {}; + + if (modelClass === 'Sequential') { + const outputLayer = this.modelLayersMap.get(this.outputLayerNames[0]); + outputData['output'] = outputLayer.output.tensor.data; + } else if (modelClass === 'Model') { + this.outputLayerNames.forEach(layerName => { + const outputLayer = this.modelLayersMap.get(layerName); + outputData[layerName] = outputLayer.output.tensor.data; + }); + } + + start = (0, _performanceNow.default)(); + this.visMap.forEach(visInstance => { + visInstance.update(); + }); + this.predictStats.visualizations = (0, _performanceNow.default)() - start; + this.isRunning = false; + return outputData; + } + + layerCall(layerName, input) { + if (!this.modelLayersMap.has(layerName)) return; + let x; + + if (input instanceof _Tensor.default) { + x = input; + } else { + x = new _Tensor.default(input.data, input.shape); + } + + const layer = this.modelLayersMap.get(layerName); + return layer.call(x); + } + + cleanup() { + _WebGL.webgl2.clearRefs(); + + this.modelLayersMap.clear(); + this.inputTensorsMap.clear(); + this.visMap.clear(); + delete this.modelWeights; + } + +} + +exports.default = Model; \ No newline at end of file diff --git a/lib/Tensor.js b/lib/Tensor.js new file mode 100644 index 0000000000..b63dc12163 --- /dev/null +++ b/lib/Tensor.js @@ -0,0 +1,386 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _WebGL = require("./WebGL2"); + +var tensorUtils = _interopRequireWildcard(require("./utils/tensorUtils")); + +var _ndarray = _interopRequireDefault(require("ndarray")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarraySqueeze = _interopRequireDefault(require("ndarray-squeeze")); + +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; } } + +class Tensor { + constructor(data, shape, options = {}) { + this.arrayType = options.type || Float32Array; + + if (data && data.length && (data instanceof this.arrayType || data instanceof Array)) { + tensorUtils.checkShape(data, shape); + + if (data instanceof this.arrayType) { + this.tensor = (0, _ndarray.default)(data, shape); + } else if (data instanceof Array) { + this.tensor = (0, _ndarray.default)(new this.arrayType(data), shape); + } + } else if (!data.length && shape.length) { + this.tensor = (0, _ndarray.default)(new this.arrayType(shape.reduce((a, b) => a * b, 1)), shape); + } else { + this.tensor = (0, _ndarray.default)(new this.arrayType([]), []); + } + } + + createGLTexture({ + type = '2d', + format = 'float', + supportsTextureFragments = false + }) { + let shape = []; + + if (this.tensor.shape.length === 1) { + shape = [1, this.tensor.shape[0]]; + this.is1D = true; + } else if (this.tensor.shape.length === 2) { + shape = this.tensor.shape; + } else if (this.tensor.shape.length === 3 && (type === '2d_array' || type === '3d')) { + shape = this.tensor.shape; + } else { + throw new Error('[Tensor] cannot create WebGL2 texture.'); + } + + this.glTextureShape = shape; + this.glTextureType = type; + this.glTextureFormat = format; + + if (type === '2d') { + if (this.glTextureShape[0] > _WebGL.MAX_TEXTURE_SIZE && supportsTextureFragments) { + this._create2DRowFragmentedGLTexture(); + } else { + this._create2DGLTexture(); + } + } else if (type === '2d_array' || type === '3d') { + this._create3DGLTexture(); + } else { + throw new Error(`[Tensor] invalid type ${type}.`); + } + } + + _create2DGLTexture() { + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + } = textureOptions; + this.glTexture = gl.createTexture(); + + _WebGL.webgl2.storeRef('texture', this.glTexture); + + gl.bindTexture(textureTarget, this.glTexture); + const shape = this.glTextureShape; + const data = this.tensor.data; + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } + + _create2DRowFragmentedGLTexture() { + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + } = textureOptions; + this.glTextureFragments = []; + this.glTextureFragmentShape = [_WebGL.MAX_TEXTURE_SIZE, this.glTextureShape[1]]; + const shape = this.glTextureFragmentShape; + const numFragments = Math.ceil(this.glTextureShape[0] / _WebGL.MAX_TEXTURE_SIZE); + let offset = 0; + + for (let k = 0; k < numFragments; k++) { + const glTexture = gl.createTexture(); + + _WebGL.webgl2.storeRef('texture', glTexture); + + gl.bindTexture(textureTarget, glTexture); + let data; + + if (k === numFragments - 1) { + data = new this.arrayType(shape[0] * shape[1]); + data.set(this.tensor.data.slice(offset, offset + shape[0] * shape[1]), 0); + } else { + data = this.tensor.data.slice(offset, offset + shape[0] * shape[1]); + } + + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + this.glTextureFragments.push(glTexture); + offset += shape[0] * shape[1]; + } + } + + _create3DGLTexture() { + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + } = textureOptions; + this.glTexture = gl.createTexture(); + + _WebGL.webgl2.storeRef('texture', this.glTexture); + + gl.bindTexture(textureTarget, this.glTexture); + const shape = this.glTextureShape; + const data = tensorUtils.data3DLayoutForGL(this.arrayType, this.tensor, this.glTextureShape); + gl.texImage3D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], shape[2], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } + + convert2DRowFragmentedGLTextureToColStack() { + if (!this.glTextureFragments || !this.glTextureFragmentShape) { + throw new Error('[Tensor] no glTextureFragments available.'); + } + + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + } = textureOptions; + + if (!this.glTextureFragmentsAsColStack) { + this.glTextureFragmentsAsColStack = gl.createTexture(); + + _WebGL.webgl2.storeRef('texture', this.glTextureFragmentsAsColStack); + + gl.bindTexture(textureTarget, this.glTextureFragmentsAsColStack); + const numFragments = this.glTextureFragments.length; + this.glTextureFragmentsAsColStackShape = [this.glTextureFragmentShape[0], this.glTextureFragmentShape[1] * numFragments]; + const shape = this.glTextureFragmentsAsColStackShape; + const data = new this.arrayType(shape.reduce((a, b) => a * b, 1)); + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } else { + gl.bindTexture(textureTarget, this.glTextureFragmentsAsColStack); + } + + const fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo); + this.glTextureFragments.forEach((texture, k) => { + gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + gl.copyTexSubImage2D(textureTarget, 0, k * this.glTextureFragmentShape[1], 0, 0, 0, this.glTextureFragmentShape[1], this.glTextureFragmentShape[0]); + }); + gl.deleteFramebuffer(fbo); + } + + removeGLTextureFragmentsAsColStack() { + if (this.glTextureFragmentsAsColStack) { + const gl = _WebGL.webgl2.context; + gl.deleteTexture(this.glTextureFragmentsAsColStack); + delete this.glTextureFragmentsAsColStack; + delete this.glTextureFragmentsAsColStackShape; + } + } + + deleteGLTexture() { + const gl = _WebGL.webgl2.context; + + if (this.glTexture) { + gl.deleteTexture(this.glTexture); + delete this.glTexture; + } + + if (this.glTextureFragments) { + this.glTextureFragments.forEach(texture => { + gl.deleteTexture(texture); + }); + delete this.glTextureFragments; + } + } + + replaceTensorData(data) { + if (data && data.length && data instanceof this.arrayType) { + this.tensor.data.set(data); + } else if (data && data.length && data instanceof Array) { + this.tensor.data.set(new this.arrayType(data)); + } else { + throw new Error('[Tensor] invalid input for replaceTensorData method.'); + } + + if (this.glTexture) { + const gl = _WebGL.webgl2.context; + + const textureOptions = _WebGL.webgl2.getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + + const { + textureTarget, + textureFormat, + textureType + } = textureOptions; + gl.bindTexture(textureTarget, this.glTexture); + const shape = this.glTextureShape; + + if (this.glTextureType === '2d') { + const data = this.tensor.data; + gl.texSubImage2D(textureTarget, 0, 0, 0, shape[1], shape[0], textureFormat, textureType, data, 0); + } else if (this.glTextureType === '2d_array' || this.glTextureType === '3d') { + const data = tensorUtils.data3DLayoutForGL(this.arrayType, this.tensor, shape); + gl.texSubImage3D(textureTarget, 0, 0, 0, 0, shape[1], shape[0], shape[2], textureFormat, textureType, data, 0); + } + } + } + + transferFromGLTexture() { + if (this.glTextureFragments) { + this.tensor = (0, _ndarray.default)(new this.arrayType(this.glTextureShape[0] * this.glTextureShape[1]), this.glTextureShape); + let offset = 0; + + for (let k = 0; k < this.glTextureFragments.length; k++) { + _WebGL.webgl2.bindOutputTexture(this.glTextureFragments[k], this.glTextureFragmentShape); + + const fragmentData = _WebGL.webgl2.readData(this.glTextureFragmentShape); + + if (k === this.glTextureFragments.length - 1) { + const truncate = this.tensor.data.length - offset; + this.tensor.data.set(fragmentData.subarray(0, truncate), offset); + } else { + this.tensor.data.set(fragmentData, offset); + } + + offset += fragmentData.length; + } + } else { + _WebGL.webgl2.bindOutputTexture(this.glTexture, this.glTextureShape); + + this.tensor = (0, _ndarray.default)(new this.arrayType([]), this.glTextureShape); + this.tensor.data = _WebGL.webgl2.readData(this.glTextureShape); + } + + if (this.is1D && this.glTextureShape[0] === 1) { + this.tensor = (0, _ndarraySqueeze.default)(this.tensor, [0]); + } + } + + reshapeTo2D() { + const axis = this.tensor.shape.length - 1; + const axisSize = this.tensor.shape[axis]; + const otherAxes = this.tensor.shape.slice(0, axis); + const otherAxesSize = otherAxes.reduce((a, b) => a * b, 1); + const reshaped = (0, _ndarray.default)(new this.arrayType(otherAxesSize * axisSize), [otherAxesSize, axisSize]); + const otherAxesData = (0, _ndarray.default)(new this.arrayType(otherAxesSize), otherAxes); + const otherAxesDataRaveled = (0, _ndarray.default)(new this.arrayType(otherAxesSize), [otherAxesSize]); + const axisSlices = Array(this.tensor.shape.length).fill(null); + + for (let n = 0; n < axisSize; n++) { + axisSlices[axis] = n; + + _ndarrayOps.default.assign(otherAxesData, this.tensor.pick(...axisSlices)); + + otherAxesDataRaveled.data = otherAxesData.data; + + _ndarrayOps.default.assign(reshaped.pick(null, n), otherAxesDataRaveled); + } + + this.originalShape = this.tensor.shape; + this.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.tensor.shape, false, axis); + this.tensor = reshaped; + this.is2DReshaped = true; + } + + reshapeFrom2D(axis = -1) { + if (!this.is2DReshaped) { + throw new Error('[Tensor] not in reshaped 2D representation.'); + } + + if (!this.originalShape) { + throw new Error('[Tensor] does not contain originalShape.'); + } + + if (axis < 0) { + axis = this.originalShape.length + axis; + } + + const channelDataSize = this.tensor.shape[0]; + const channels = this.tensor.shape[1]; + const reshaped = (0, _ndarray.default)(new this.arrayType(this.originalShape.reduce((a, b) => a * b, 1)), this.originalShape); + const channelDataRaveled = (0, _ndarray.default)(new this.arrayType(channelDataSize), [channelDataSize]); + const unraveledChannelShape = [...this.originalShape.slice(0, axis), ...this.originalShape.slice(axis + 1)]; + const unraveledChannel = (0, _ndarray.default)(new this.arrayType(unraveledChannelShape.reduce((a, b) => a * b, 1)), unraveledChannelShape); + const axisSlices = Array(this.originalShape.length).fill(null); + + for (let n = 0; n < channels; n++) { + _ndarrayOps.default.assign(channelDataRaveled, this.tensor.pick(null, n)); + + unraveledChannel.data = channelDataRaveled.data; + axisSlices[axis] = n; + + _ndarrayOps.default.assign(reshaped.pick(...axisSlices), unraveledChannel); + } + + this.tensor = reshaped; + } + + reshapeTo2DSquare() { + const squareDim = Math.ceil(Math.sqrt(this.tensor.size)); + const reshaped = (0, _ndarray.default)(new this.arrayType(squareDim ** 2), [squareDim, squareDim]); + reshaped.data.set(this.tensor.data); + this.originalShape = this.tensor.shape; + this.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.tensor.shape, true); + this.tensor = reshaped; + this.is2DSquareReshaped = true; + } + + reshapeFrom2DSquare() { + if (!this.is2DSquareReshaped) { + throw new Error('[Tensor] not in reshaped 2D square representation.'); + } + + if (!this.originalShape) { + throw new Error('[Tensor] does not contain originalShape.'); + } + + const size = this.originalShape.reduce((a, b) => a * b, 1); + const reshaped = (0, _ndarray.default)(new this.arrayType(size), this.originalShape); + reshaped.data.set(this.tensor.data.subarray(0, size)); + this.tensor = reshaped; + } + +} + +exports.default = Tensor; \ No newline at end of file diff --git a/lib/WebGL2.js b/lib/WebGL2.js new file mode 100644 index 0000000000..99f0f4897c --- /dev/null +++ b/lib/WebGL2.js @@ -0,0 +1,281 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.MAX_TEXTURE_IMAGE_UNITS = exports.MAX_TEXTURE_SIZE = exports.webgl2 = void 0; +const vertexShaderSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec3 position;\r\nin vec2 texcoord;\r\nout vec2 outTex;\r\n\r\nvoid main () {\r\n gl_Position = vec4(position, 1.0);\r\n\toutTex = texcoord;\r\n}\r\n"; + +class WebGL2 { + constructor() { + this.isSupported = false; + this.vertexShader = null; + + if (typeof window !== 'undefined') { + this.canvas = document.createElement('canvas'); + this.context = this.canvas.getContext('webgl2'); + const gl = this.context; + + if (gl) { + this.isSupported = true; + gl.getExtension('EXT_color_buffer_float'); + this.MAX_TEXTURE_SIZE = gl.getParameter(gl.MAX_TEXTURE_SIZE); + this.MAX_TEXTURE_IMAGE_UNITS = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + this.init(); + } else { + console.log('Unable to initialize WebGL2 -- your browser may not support it.'); + } + } + + this._refs = { + textures: [], + buffers: [] + }; + } + + init() { + this.createCommonVertexShader(); + } + + createCommonVertexShader() { + const gl = this.context; + const vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader, vertexShaderSource); + gl.compileShader(vertexShader); + const success = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS); + + if (!success) { + console.error(gl.getShaderInfoLog(vertexShader)); + gl.deleteShader(vertexShader); + this.isSupported = false; + } + + this.vertexShader = vertexShader; + } + + compileProgram(source) { + const gl = this.context; + const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader, source); + gl.compileShader(fragmentShader); + let success = gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS); + + if (!success) { + console.error(gl.getShaderInfoLog(fragmentShader)); + gl.deleteShader(fragmentShader); + this.isSupported = false; + } + + const program = gl.createProgram(); + gl.attachShader(program, this.vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + success = gl.getProgramParameter(program, gl.LINK_STATUS); + + if (!success) { + console.error(gl.getProgramInfoLog(program)); + this.isSupported = false; + } + + this.setupVertices(program); + return program; + } + + setupVertices(program) { + const gl = this.context; + const position = gl.getAttribLocation(program, 'position'); + const positionVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, positionVertexObj); + this.storeRef('buffer', positionVertexObj); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]), gl.STATIC_DRAW); + gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(position); + const texcoord = gl.getAttribLocation(program, 'texcoord'); + const texcoordVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordVertexObj); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]), gl.STATIC_DRAW); + gl.vertexAttribPointer(texcoord, 2, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(texcoord); + this.storeRef('buffer', texcoordVertexObj); + const indicesVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesVertexObj); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW); + this.storeRef('buffer', indicesVertexObj); + } + + selectProgram(program) { + const gl = this.context; + gl.useProgram(program); + } + + bindUniforms(program, uniforms) { + const gl = this.context; + uniforms.forEach(({ + value, + type, + name + }) => { + const loc = gl.getUniformLocation(program, name); + + if (type === 'float') { + gl.uniform1f(loc, value); + } else if (type === 'int' || type === 'bool') { + gl.uniform1i(loc, value); + } + }); + } + + bindInputTextures(program, inputs, k) { + const gl = this.context; + inputs.forEach(({ + input, + name + }, i) => { + gl.activeTexture(gl.TEXTURE0 + i); + + if (input.glTextureFragments) { + if (input.glTextureFragmentsAsColStack) { + const { + textureTarget + } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat); + gl.bindTexture(textureTarget, input.glTextureFragmentsAsColStack); + } else { + const { + textureTarget + } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat); + gl.bindTexture(textureTarget, input.glTextureFragments[k]); + } + } else { + const { + textureTarget + } = this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat); + gl.bindTexture(textureTarget, input.glTexture); + } + + gl.uniform1i(gl.getUniformLocation(program, name), i); + }); + } + + bindOutputTexture(outputTexture, shape) { + const gl = this.context; + gl.viewport(0, 0, shape[1], shape[0]); + this.framebuffer = this.framebuffer || gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0); + } + + runProgram({ + program, + output, + inputs, + uniforms, + supportsTextureFragments = false + }) { + if (!program) throw new Error('[WebGL2] missing program'); + if (!output) throw new Error('[WebGL2] missing output'); + if (!inputs) throw new Error('[WebGL2] missing inputs'); + const gl = this.context; + this.selectProgram(program); + + if (uniforms && Array.isArray(uniforms)) { + this.bindUniforms(program, uniforms); + } + + if (output.glTextureFragments) { + if (!supportsTextureFragments) { + throw new Error('[WebGL2] program does not support texture fragments'); + } + + const inputsWithFragments = inputs.filter(obj => obj.input.glTextureFragments && !obj.input.glTextureFragmentsAsColStack); + const numFragments = output.glTextureFragments.length; + + if (inputsWithFragments.some(obj => obj.input.glTextureFragments.length !== numFragments)) { + throw new Error('[WebGL2] number of texture fragments in inputs and output do not match'); + } + + for (let k = 0; k < numFragments; k++) { + this.bindOutputTexture(output.glTextureFragments[k], output.glTextureFragmentShape); + this.bindInputTextures(program, inputs, k); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + } + } else { + this.bindOutputTexture(output.glTexture, output.glTextureShape); + this.bindInputTextures(program, inputs); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + } + } + + readData(shape) { + const gl = this.context; + const buf = new ArrayBuffer(shape[0] * shape[1] * 4 * 4); + const view = new Float32Array(buf); + gl.readPixels(0, 0, shape[1], shape[0], gl.RGBA, gl.FLOAT, view); + const out = []; + + for (let i = 0; i < view.length; i += 4) { + out.push(view[i]); + } + + return new Float32Array(out); + } + + getWebGLTextureOptions(type, format) { + const gl = this.context; + const targetMap = { + '2d': gl.TEXTURE_2D, + '2d_array': gl.TEXTURE_2D_ARRAY, + '3d': gl.TEXTURE_3D + }; + const internalFormatMap = { + float: gl.R32F, + int: gl.R32I + }; + const formatMap = { + float: gl.RED, + int: gl.RED_INTEGER + }; + const typeMap = { + float: gl.FLOAT, + int: gl.INT + }; + const textureTarget = targetMap[type]; + const textureInternalFormat = internalFormatMap[format]; + const textureFormat = formatMap[format]; + const textureType = typeMap[format]; + return { + textureTarget, + textureInternalFormat, + textureFormat, + textureType + }; + } + + storeRef(type, obj) { + if (type === 'texture') { + this._refs.textures.push(obj); + } else if (type === 'buffer') { + this._refs.buffers.push(obj); + } + } + + clearRefs() { + const gl = this.context; + + this._refs.textures.forEach(texture => gl.deleteTexture(texture)); + + this._refs.buffers.forEach(buffer => gl.deleteBuffer(buffer)); + + this._refs = { + textures: [], + buffers: [] + }; + } + +} + +const webgl2 = new WebGL2(); +exports.webgl2 = webgl2; +const MAX_TEXTURE_SIZE = webgl2.MAX_TEXTURE_SIZE; +exports.MAX_TEXTURE_SIZE = MAX_TEXTURE_SIZE; +const MAX_TEXTURE_IMAGE_UNITS = webgl2.MAX_TEXTURE_IMAGE_UNITS; +exports.MAX_TEXTURE_IMAGE_UNITS = MAX_TEXTURE_IMAGE_UNITS; \ No newline at end of file diff --git a/lib/activations/elu.js b/lib/activations/elu.js new file mode 100644 index 0000000000..477bdb4653 --- /dev/null +++ b/lib/activations/elu.js @@ -0,0 +1,25 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = elu; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _elu = (0, _cwise.default)({ + args: ['array', 'scalar'], + body: function (_x, alpha) { + _x = Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1); + } +}); + +function elu(x, opts = {}) { + const { + alpha = 1.0 + } = opts; + + _elu(x.tensor, alpha); +} \ No newline at end of file diff --git a/lib/activations/hard_sigmoid.js b/lib/activations/hard_sigmoid.js new file mode 100644 index 0000000000..fbb2fb915f --- /dev/null +++ b/lib/activations/hard_sigmoid.js @@ -0,0 +1,27 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = hard_sigmoid; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _hard_sigmoid = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x = _x * 0.2 + 0.5; + + if (_x <= 0) { + _x = 0; + } else if (_x >= 1) { + _x = 1; + } + } +}); + +function hard_sigmoid(x) { + _hard_sigmoid(x.tensor); +} \ No newline at end of file diff --git a/lib/activations/index.js b/lib/activations/index.js new file mode 100644 index 0000000000..01201b9568 --- /dev/null +++ b/lib/activations/index.js @@ -0,0 +1,87 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "softmax", { + enumerable: true, + get: function () { + return _softmax.default; + } +}); +Object.defineProperty(exports, "elu", { + enumerable: true, + get: function () { + return _elu.default; + } +}); +Object.defineProperty(exports, "selu", { + enumerable: true, + get: function () { + return _selu.default; + } +}); +Object.defineProperty(exports, "softplus", { + enumerable: true, + get: function () { + return _softplus.default; + } +}); +Object.defineProperty(exports, "softsign", { + enumerable: true, + get: function () { + return _softsign.default; + } +}); +Object.defineProperty(exports, "relu", { + enumerable: true, + get: function () { + return _relu.default; + } +}); +Object.defineProperty(exports, "tanh", { + enumerable: true, + get: function () { + return _tanh.default; + } +}); +Object.defineProperty(exports, "sigmoid", { + enumerable: true, + get: function () { + return _sigmoid.default; + } +}); +Object.defineProperty(exports, "hard_sigmoid", { + enumerable: true, + get: function () { + return _hard_sigmoid.default; + } +}); +Object.defineProperty(exports, "linear", { + enumerable: true, + get: function () { + return _linear.default; + } +}); + +var _softmax = _interopRequireDefault(require("./softmax")); + +var _elu = _interopRequireDefault(require("./elu")); + +var _selu = _interopRequireDefault(require("./selu")); + +var _softplus = _interopRequireDefault(require("./softplus")); + +var _softsign = _interopRequireDefault(require("./softsign")); + +var _relu = _interopRequireDefault(require("./relu")); + +var _tanh = _interopRequireDefault(require("./tanh")); + +var _sigmoid = _interopRequireDefault(require("./sigmoid")); + +var _hard_sigmoid = _interopRequireDefault(require("./hard_sigmoid")); + +var _linear = _interopRequireDefault(require("./linear")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/activations/linear.js b/lib/activations/linear.js new file mode 100644 index 0000000000..59fdcc4268 --- /dev/null +++ b/lib/activations/linear.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = linear; + +function linear(x) { + return x; +} \ No newline at end of file diff --git a/lib/activations/programSources.js b/lib/activations/programSources.js new file mode 100644 index 0000000000..928a98fec9 --- /dev/null +++ b/lib/activations/programSources.js @@ -0,0 +1,26 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.linear = exports.hard_sigmoid = exports.sigmoid = exports.tanh = exports.relu = exports.softsign = exports.softplus = exports.selu = exports.elu = exports.softmax = void 0; +const softmaxProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float maxval = 0.0;\r\n for (int i = 0; i < int(size[0]); ++i) {\r\n float val = texelFetch(x, ivec2(i, out_y), 0).r;\r\n if (i == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n\r\n float sum = 0.0;\r\n for (int i = 0; i < int(size[0]); ++i) {\r\n float val = texelFetch(x, ivec2(i, out_y), 0).r;\r\n sum += exp(val - maxval);\r\n }\r\n\r\n outColor = exp(texture(x, vec2(outTex.x, outTex.y)) - maxval) / sum;\r\n}\r\n"; +exports.softmax = softmaxProgramSource; +const eluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n float alpha = 1.0;\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0);\r\n}\r\n"; +exports.elu = eluProgramSource; +const seluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n float alpha = 1.6732632423543772848170429916717;\r\n float scale = 1.0507009873554804934193349852946;\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = scale * (max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0));\r\n}\r\n"; +exports.selu = seluProgramSource; +const softplusProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = log(1.0 + exp(texture(x, vec2(outTex.x, outTex.y))));\r\n}\r\n"; +exports.softplus = softplusProgramSource; +const softsignProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n v /= 1.0 + abs(v);\r\n outColor = v;\r\n}\r\n"; +exports.softsign = softsignProgramSource; +const reluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0);\r\n}\r\n"; +exports.relu = reluProgramSource; +const tanhProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = tanh(v);\r\n}\r\n"; +exports.tanh = tanhProgramSource; +const sigmoidProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = 1.0 / (1.0 + exp(-1.0 * texture(x, vec2(outTex.x, outTex.y))));\r\n}\r\n"; +exports.sigmoid = sigmoidProgramSource; +const hardSigmoidProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n v = v * 0.2 + 0.5;\r\n v = max(v, 0.0);\r\n v = min(v, 1.0);\r\n outColor = v;\r\n}\r\n"; +exports.hard_sigmoid = hardSigmoidProgramSource; +const linearProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = texture(x, vec2(outTex.x, outTex.y));\r\n}\r\n"; +exports.linear = linearProgramSource; \ No newline at end of file diff --git a/lib/activations/relu.js b/lib/activations/relu.js new file mode 100644 index 0000000000..8dc861607a --- /dev/null +++ b/lib/activations/relu.js @@ -0,0 +1,38 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = relu; + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _Tensor = _interopRequireDefault(require("../Tensor")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function relu(x, opts = {}) { + const { + alpha = 0, + maxValue = null + } = opts; + let neg; + + if (alpha !== 0) { + neg = new _Tensor.default([], x.tensor.shape); + + _ndarrayOps.default.mins(neg.tensor, x.tensor, 0); + + _ndarrayOps.default.mulseq(neg.tensor, alpha); + } + + _ndarrayOps.default.maxseq(x.tensor, 0); + + if (maxValue) { + _ndarrayOps.default.minseq(x.tensor, maxValue); + } + + if (neg) { + _ndarrayOps.default.addeq(x.tensor, neg.tensor); + } +} \ No newline at end of file diff --git a/lib/activations/selu.js b/lib/activations/selu.js new file mode 100644 index 0000000000..56ec53c7cd --- /dev/null +++ b/lib/activations/selu.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = selu; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _selu = (0, _cwise.default)({ + args: ['array', 'scalar'], + body: function (_x) { + const alpha = 1.6732632423543772848170429916717; + const scale = 1.0507009873554804934193349852946; + _x = scale * (Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1)); + } +}); + +function selu(x) { + _selu(x.tensor); +} \ No newline at end of file diff --git a/lib/activations/sigmoid.js b/lib/activations/sigmoid.js new file mode 100644 index 0000000000..c5c124653e --- /dev/null +++ b/lib/activations/sigmoid.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = sigmoid; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _sigmoid = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x = 1 / (1 + Math.exp(-_x)); + } +}); + +function sigmoid(x) { + _sigmoid(x.tensor); +} \ No newline at end of file diff --git a/lib/activations/softmax.js b/lib/activations/softmax.js new file mode 100644 index 0000000000..98547ada23 --- /dev/null +++ b/lib/activations/softmax.js @@ -0,0 +1,38 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = softmax; + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function softmax(x) { + if (x.tensor.shape.length === 1) { + const maxval = _ndarrayOps.default.sup(x.tensor); + + _ndarrayOps.default.subseq(x.tensor, maxval); + + _ndarrayOps.default.expeq(x.tensor); + + const sum = _ndarrayOps.default.sum(x.tensor); + + _ndarrayOps.default.divseq(x.tensor, sum); + } else if (x.tensor.shape.length === 2) { + for (let i = 0; i < x.tensor.shape[0]; i++) { + const maxval = _ndarrayOps.default.sup(x.tensor.pick(i, null)); + + _ndarrayOps.default.subseq(x.tensor.pick(i, null), maxval); + + _ndarrayOps.default.expeq(x.tensor.pick(i, null)); + + const sum = _ndarrayOps.default.sum(x.tensor.pick(i, null)); + + _ndarrayOps.default.divseq(x.tensor.pick(i, null), sum); + } + } else { + throw new Error(`[activations.softmax] tensor shape ${x.tensor.shape} not supported.`); + } +} \ No newline at end of file diff --git a/lib/activations/softplus.js b/lib/activations/softplus.js new file mode 100644 index 0000000000..6affd45ff2 --- /dev/null +++ b/lib/activations/softplus.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = softplus; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _softplus = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x = Math.log(Math.exp(_x) + 1); + } +}); + +function softplus(x) { + _softplus(x.tensor); +} \ No newline at end of file diff --git a/lib/activations/softsign.js b/lib/activations/softsign.js new file mode 100644 index 0000000000..a4e81e4f83 --- /dev/null +++ b/lib/activations/softsign.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = softsign; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _softsign = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x /= 1 + Math.abs(_x); + } +}); + +function softsign(x) { + _softsign(x.tensor); +} \ No newline at end of file diff --git a/lib/activations/tanh.js b/lib/activations/tanh.js new file mode 100644 index 0000000000..98f90ed086 --- /dev/null +++ b/lib/activations/tanh.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = tanh; + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const _tanh = (0, _cwise.default)({ + args: ['array'], + body: function (_x) { + _x = Math.tanh(_x); + } +}); + +function tanh(x) { + _tanh(x.tensor); +} \ No newline at end of file diff --git a/lib/ask.js b/lib/ask.js deleted file mode 100644 index 9c3be69901..0000000000 --- a/lib/ask.js +++ /dev/null @@ -1,67 +0,0 @@ -const async = require('async') -const inquirer = require('inquirer') -const evaluate = require('./eval') - -// Support types from prompt-for which was used before -const promptMapping = { - string: 'input', - boolean: 'confirm' -} - -/** - * Ask questions, return results. - * - * @param {Object} prompts - * @param {Object} data - * @param {Function} done - */ - -module.exports = function ask (prompts, data, done) { - async.eachSeries(Object.keys(prompts), (key, next) => { - prompt(data, key, prompts[key], next) - }, done) -} - -/** - * Inquirer prompt wrapper. - * - * @param {Object} data - * @param {String} key - * @param {Object} prompt - * @param {Function} done - */ - -function prompt (data, key, prompt, done) { - // skip prompts whose when condition is not met - if (prompt.when && !evaluate(prompt.when, data)) { - return done() - } - - let promptDefault = prompt.default - if (typeof prompt.default === 'function') { - promptDefault = function () { - return prompt.default.bind(this)(data) - } - } - - inquirer.prompt([{ - type: promptMapping[prompt.type] || prompt.type, - name: key, - message: prompt.message || prompt.label || key, - default: promptDefault, - choices: prompt.choices || [], - validate: prompt.validate || (() => true) - }]).then(answers => { - if (Array.isArray(answers[key])) { - data[key] = {} - answers[key].forEach(multiChoiceAnswer => { - data[key][multiChoiceAnswer] = true - }) - } else if (typeof answers[key] === 'string') { - data[key] = answers[key].replace(/"/g, '\\"') - } else { - data[key] = answers[key] - } - done() - }).catch(done) -} diff --git a/lib/check-version.js b/lib/check-version.js deleted file mode 100644 index 98f20ac834..0000000000 --- a/lib/check-version.js +++ /dev/null @@ -1,31 +0,0 @@ -const request = require('request') -const semver = require('semver') -const chalk = require('chalk') -const packageConfig = require('../package.json') - -module.exports = done => { - // Ensure minimum supported node version is used - if (!semver.satisfies(process.version, packageConfig.engines.node)) { - return console.log(chalk.red( - ' You must upgrade node to >=' + packageConfig.engines.node + '.x to use vue-cli' - )) - } - - request({ - url: 'https://registry.npmjs.org/vue-cli', - timeout: 1000 - }, (err, res, body) => { - if (!err && res.statusCode === 200) { - const latestVersion = JSON.parse(body)['dist-tags'].latest - const localVersion = packageConfig.version - if (semver.lt(localVersion, latestVersion)) { - console.log(chalk.yellow(' A newer version of vue-cli is available.')) - console.log() - console.log(' latest: ' + chalk.green(latestVersion)) - console.log(' installed: ' + chalk.red(localVersion)) - console.log() - } - } - done() - }) -} diff --git a/lib/eval.js b/lib/eval.js deleted file mode 100644 index 1e5787ca01..0000000000 --- a/lib/eval.js +++ /dev/null @@ -1,16 +0,0 @@ -const chalk = require('chalk') - -/** - * Evaluate an expression in meta.json in the context of - * prompt answers data. - */ - -module.exports = function evaluate (exp, data) { - /* eslint-disable no-new-func */ - const fn = new Function('data', 'with (data) { return ' + exp + '}') - try { - return fn(data) - } catch (e) { - console.error(chalk.red('Error when evaluating filter condition: ' + exp)) - } -} diff --git a/lib/filter.js b/lib/filter.js deleted file mode 100644 index 5cbadb0063..0000000000 --- a/lib/filter.js +++ /dev/null @@ -1,20 +0,0 @@ -const match = require('minimatch') -const evaluate = require('./eval') - -module.exports = (files, filters, data, done) => { - if (!filters) { - return done() - } - const fileNames = Object.keys(files) - Object.keys(filters).forEach(glob => { - fileNames.forEach(file => { - if (match(file, glob, { dot: true })) { - const condition = filters[glob] - if (!evaluate(condition, data)) { - delete files[file] - } - } - }) - }) - done() -} diff --git a/lib/generate.js b/lib/generate.js deleted file mode 100644 index 8493f96f74..0000000000 --- a/lib/generate.js +++ /dev/null @@ -1,158 +0,0 @@ -const chalk = require('chalk') -const Metalsmith = require('metalsmith') -const Handlebars = require('handlebars') -const async = require('async') -const render = require('consolidate').handlebars.render -const path = require('path') -const multimatch = require('multimatch') -const getOptions = require('./options') -const ask = require('./ask') -const filter = require('./filter') -const logger = require('./logger') - -// register handlebars helper -Handlebars.registerHelper('if_eq', function (a, b, opts) { - return a === b - ? opts.fn(this) - : opts.inverse(this) -}) - -Handlebars.registerHelper('unless_eq', function (a, b, opts) { - return a === b - ? opts.inverse(this) - : opts.fn(this) -}) - -/** - * Generate a template given a `src` and `dest`. - * - * @param {String} name - * @param {String} src - * @param {String} dest - * @param {Function} done - */ - -module.exports = function generate (name, src, dest, done) { - const opts = getOptions(name, src) - const metalsmith = Metalsmith(path.join(src, 'template')) - const data = Object.assign(metalsmith.metadata(), { - destDirName: name, - inPlace: dest === process.cwd(), - noEscape: true - }) - opts.helpers && Object.keys(opts.helpers).map(key => { - Handlebars.registerHelper(key, opts.helpers[key]) - }) - - const helpers = { chalk, logger } - - if (opts.metalsmith && typeof opts.metalsmith.before === 'function') { - opts.metalsmith.before(metalsmith, opts, helpers) - } - - metalsmith.use(askQuestions(opts.prompts)) - .use(filterFiles(opts.filters)) - .use(renderTemplateFiles(opts.skipInterpolation)) - - if (typeof opts.metalsmith === 'function') { - opts.metalsmith(metalsmith, opts, helpers) - } else if (opts.metalsmith && typeof opts.metalsmith.after === 'function') { - opts.metalsmith.after(metalsmith, opts, helpers) - } - - metalsmith.clean(false) - .source('.') // start from template root instead of `./src` which is Metalsmith's default for `source` - .destination(dest) - .build((err, files) => { - done(err) - if (typeof opts.complete === 'function') { - const helpers = { chalk, logger, files } - opts.complete(data, helpers) - } else { - logMessage(opts.completeMessage, data) - } - }) - - return data -} - -/** - * Create a middleware for asking questions. - * - * @param {Object} prompts - * @return {Function} - */ - -function askQuestions (prompts) { - return (files, metalsmith, done) => { - ask(prompts, metalsmith.metadata(), done) - } -} - -/** - * Create a middleware for filtering files. - * - * @param {Object} filters - * @return {Function} - */ - -function filterFiles (filters) { - return (files, metalsmith, done) => { - filter(files, filters, metalsmith.metadata(), done) - } -} - -/** - * Template in place plugin. - * - * @param {Object} files - * @param {Metalsmith} metalsmith - * @param {Function} done - */ - -function renderTemplateFiles (skipInterpolation) { - skipInterpolation = typeof skipInterpolation === 'string' - ? [skipInterpolation] - : skipInterpolation - return (files, metalsmith, done) => { - const keys = Object.keys(files) - const metalsmithMetadata = metalsmith.metadata() - async.each(keys, (file, next) => { - // skipping files with skipInterpolation option - if (skipInterpolation && multimatch([file], skipInterpolation, { dot: true }).length) { - return next() - } - const str = files[file].contents.toString() - // do not attempt to render files that do not have mustaches - if (!/{{([^{}]+)}}/g.test(str)) { - return next() - } - render(str, metalsmithMetadata, (err, res) => { - if (err) { - err.message = `[${file}] ${err.message}` - return next(err) - } - files[file].contents = new Buffer(res) - next() - }) - }, done) - } -} - -/** - * Display template complete message. - * - * @param {String} message - * @param {Object} data - */ - -function logMessage (message, data) { - if (!message) return - render(message, data, (err, res) => { - if (err) { - console.error('\n Error when rendering template complete message: ' + err.message.trim()) - } else { - console.log('\n' + res.split(/\r?\n/g).map(line => ' ' + line).join('\n')) - } - }) -} diff --git a/lib/git-user.js b/lib/git-user.js deleted file mode 100644 index 4583b0f9f0..0000000000 --- a/lib/git-user.js +++ /dev/null @@ -1,15 +0,0 @@ -const exec = require('child_process').execSync - -module.exports = () => { - let name - let email - - try { - name = exec('git config --get user.name') - email = exec('git config --get user.email') - } catch (e) {} - - name = name && JSON.stringify(name.toString().trim()).slice(1, -1) - email = email && (' <' + email.toString().trim() + '>') - return (name || '') + (email || '') -} diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000000..1908517b5f --- /dev/null +++ b/lib/index.js @@ -0,0 +1,45 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Model", { + enumerable: true, + get: function () { + return _Model.default; + } +}); +Object.defineProperty(exports, "Tensor", { + enumerable: true, + get: function () { + return _Tensor.default; + } +}); +exports.testUtils = exports.layers = exports.activations = exports.GPU_SUPPORT = void 0; + +require("@babel/polyfill"); + +var _Model = _interopRequireDefault(require("./Model")); + +var _Tensor = _interopRequireDefault(require("./Tensor")); + +var _WebGL = require("./WebGL2"); + +var activations = _interopRequireWildcard(require("./activations")); + +exports.activations = activations; + +var layers = _interopRequireWildcard(require("./layers")); + +exports.layers = layers; + +var testUtils = _interopRequireWildcard(require("./utils/testUtils")); + +exports.testUtils = testUtils; + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const GPU_SUPPORT = _WebGL.webgl2.isSupported; +exports.GPU_SUPPORT = GPU_SUPPORT; \ No newline at end of file diff --git a/lib/layers/InputLayer.js b/lib/layers/InputLayer.js new file mode 100644 index 0000000000..765af7a558 --- /dev/null +++ b/lib/layers/InputLayer.js @@ -0,0 +1,83 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); + +var _Layer = _interopRequireDefault(require("../Layer")); + +var _Tensor = _interopRequireDefault(require("../Tensor")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class InputLayer extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'InputLayer'; + const { + shape = [] + } = attrs; + this.shape = attrs.batch_input_shape && attrs.batch_input_shape.length ? attrs.batch_input_shape.slice(1) : shape; + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + if (!(0, _isEqual2.default)(this.inputShape, this.shape)) { + this.throwError(`input tensor shape ${x.tensor.shape} does not match specified shape ${this.shape}.`); + } + + this.output = new _Tensor.default(x.tensor.data, x.tensor.shape); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + this.inputShape = x.tensor.shape; + } else { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + } + + if (!(0, _isEqual2.default)(this.inputShape, this.shape)) { + this.throwError(`input tensor shape ${x.tensor.shape} does not match specified shape ${this.shape}.`); + } + + if (!x.glTexture) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } else if (x.tensor.shape.length > 2) { + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + } + + this.output = x; + } + +} + +exports.default = InputLayer; \ No newline at end of file diff --git a/lib/layers/advanced_activations/ELU.js b/lib/layers/advanced_activations/ELU.js new file mode 100644 index 0000000000..9ab1acb687 --- /dev/null +++ b/lib/layers/advanced_activations/ELU.js @@ -0,0 +1,126 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform float alpha;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0);\r\n}\r\n"; + +class ELU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + + _initialiseProps.call(this); + + this.layerClass = 'ELU'; + const { + alpha = 1.0 + } = attrs; + this.alpha = alpha; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = x; + + this._compute(this.output.tensor, this.alpha); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.alpha, + type: 'float', + name: 'alpha' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = ELU; + +var _initialiseProps = function () { + Object.defineProperty(this, "_compute", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'scalar'], + body: function (_x, alpha) { + _x = Math.max(_x, 0) + alpha * (Math.exp(Math.min(_x, 0)) - 1); + } + }) + }); +}; \ No newline at end of file diff --git a/lib/layers/advanced_activations/LeakyReLU.js b/lib/layers/advanced_activations/LeakyReLU.js new file mode 100644 index 0000000000..7c5a9bf761 --- /dev/null +++ b/lib/layers/advanced_activations/LeakyReLU.js @@ -0,0 +1,110 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _activations = require("../../activations"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform float alpha;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + alpha * min(v, 0.0);\r\n}\r\n"; + +class LeakyReLU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'LeakyReLU'; + const { + alpha = 0.3 + } = attrs; + this.alpha = alpha; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = x; + (0, _activations.relu)(this.output, { + alpha: this.alpha + }); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.alpha, + type: 'float', + name: 'alpha' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = LeakyReLU; \ No newline at end of file diff --git a/lib/layers/advanced_activations/PReLU.js b/lib/layers/advanced_activations/PReLU.js new file mode 100644 index 0000000000..7ad0ba94bb --- /dev/null +++ b/lib/layers/advanced_activations/PReLU.js @@ -0,0 +1,115 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D alpha;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n vec4 a = texture(alpha, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + a * min(v, 0.0);\r\n}\r\n"; + +class PReLU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + Object.defineProperty(this, "_compute", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array'], + body: function (_x, alpha) { + _x = Math.max(_x, 0) + alpha * Math.min(_x, 0); + } + }) + }); + this.layerClass = 'PReLU'; + this.params = ['alpha']; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = x; + + this._compute(this.output.tensor, this.weights['alpha'].tensor); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.weights['alpha'], + name: 'alpha' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = PReLU; \ No newline at end of file diff --git a/lib/layers/advanced_activations/ThresholdedReLU.js b/lib/layers/advanced_activations/ThresholdedReLU.js new file mode 100644 index 0000000000..a909c56d3c --- /dev/null +++ b/lib/layers/advanced_activations/ThresholdedReLU.js @@ -0,0 +1,126 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _cwise = _interopRequireDefault(require("cwise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform float theta;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = v * float(greaterThan(v, vec4(theta)));\r\n}\r\n"; + +class ThresholdedReLU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + + _initialiseProps.call(this); + + this.layerClass = 'ThresholdedReLU'; + const { + theta = 1 + } = attrs; + this.theta = theta; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = x; + + this._compute(this.output.tensor, this.theta); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.theta, + type: 'float', + name: 'theta' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = ThresholdedReLU; + +var _initialiseProps = function () { + Object.defineProperty(this, "_compute", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'scalar'], + body: function (_x, theta) { + _x = _x * Number(_x > theta); + } + }) + }); +}; \ No newline at end of file diff --git a/lib/layers/advanced_activations/index.js b/lib/layers/advanced_activations/index.js new file mode 100644 index 0000000000..2acd8b6d96 --- /dev/null +++ b/lib/layers/advanced_activations/index.js @@ -0,0 +1,39 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "LeakyReLU", { + enumerable: true, + get: function () { + return _LeakyReLU.default; + } +}); +Object.defineProperty(exports, "PReLU", { + enumerable: true, + get: function () { + return _PReLU.default; + } +}); +Object.defineProperty(exports, "ELU", { + enumerable: true, + get: function () { + return _ELU.default; + } +}); +Object.defineProperty(exports, "ThresholdedReLU", { + enumerable: true, + get: function () { + return _ThresholdedReLU.default; + } +}); + +var _LeakyReLU = _interopRequireDefault(require("./LeakyReLU")); + +var _PReLU = _interopRequireDefault(require("./PReLU")); + +var _ELU = _interopRequireDefault(require("./ELU")); + +var _ThresholdedReLU = _interopRequireDefault(require("./ThresholdedReLU")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/convolutional/Conv1D.js b/lib/layers/convolutional/Conv1D.js new file mode 100644 index 0000000000..3636d59a49 --- /dev/null +++ b/lib/layers/convolutional/Conv1D.js @@ -0,0 +1,118 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _Conv2D = _interopRequireDefault(require("./Conv2D")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarraySqueeze = _interopRequireDefault(require("ndarray-squeeze")); + +var _ndarrayUnsqueeze = _interopRequireDefault(require("ndarray-unsqueeze")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Conv1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Conv1D'; + const { + filters = 1, + kernel_size = 1, + strides = 1, + padding = 'valid', + dilation_rate = 1, + activation = 'linear', + use_bias = true + } = attrs; + + if (padding !== 'valid' && padding !== 'same') { + this.throwError('Invalid padding.'); + } + + if (dilation_rate !== 1 && strides !== 1) { + this.throwError('Incompatible combination of dilation_rate with strides.'); + } + + this.use_bias = use_bias; + this.params = this.use_bias ? ['kernel', 'bias'] : ['kernel']; + const conv2dAttrs = { + filters, + kernel_size: [kernel_size, 1], + strides: [strides, 1], + padding, + data_format: 'channels_first', + dilation_rate, + activation, + use_bias + }; + this._conv2dAttrs = conv2dAttrs; + this._conv2d = new _Conv2D.default(Object.assign(conv2dAttrs, { + gpu: attrs.gpu + })); + } + + setWeights(weightsArr) { + weightsArr[0].tensor = (0, _ndarrayUnsqueeze.default)(weightsArr[0].tensor).transpose(2, 1, 0, 3); + + this._conv2d.setWeights(weightsArr); + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const input = new _Tensor.default(x.tensor.data, x.tensor.shape); + input.tensor = (0, _ndarrayUnsqueeze.default)(input.tensor).transpose(0, 2, 1); + + const conv2dOutput = this._conv2d.call(input); + + this.outputShape = [0, 2].map(i => this._conv2d.outputShape[i]); + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor, (0, _ndarraySqueeze.default)(conv2dOutput.tensor).transpose(1, 0, 2)); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const inputShape = x.tensor.shape; + const input = new _Tensor.default([], inputShape); + Object.assign(input, x); + input.glTextureShape = inputShape; + input.is2DReshaped = true; + input.originalShape = [inputShape[0], 1, inputShape[1]]; + input.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(input.originalShape, false, -1); + this.output = this._conv2d.call(input); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Conv1D; \ No newline at end of file diff --git a/lib/layers/convolutional/Conv2D.js b/lib/layers/convolutional/Conv2D.js new file mode 100644 index 0000000000..f61e049c98 --- /dev/null +++ b/lib/layers/convolutional/Conv2D.js @@ -0,0 +1,457 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const mapInputFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(indexMap, 0);\r\n int out_x = int(float(outputSize[0]) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n int fragmentIndex = int(floor(float(rowIndex) / float(inputSize[1])));\r\n rowIndex = int(mod(float(rowIndex), float(inputSize[1])));\r\n colIndex = fragmentIndex * inputCols + colIndex;\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class Conv2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Conv2D'; + const { + filters = 1, + kernel_size = [3, 3], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + dilation_rate = [1, 1], + activation = 'linear', + use_bias = true + } = attrs; + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size]; + } else { + this.kernelShape = [filters, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else { + this.strides = [strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format; + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + if (Array.isArray(dilation_rate)) { + this.dilationRate = dilation_rate; + } else { + this.dilationRate = [dilation_rate, dilation_rate]; + } + + if ((this.dilationRate[0] !== 1 || this.dilationRate[1] !== 1) && (this.strides[0] !== 1 || this.strides[1] !== 1)) { + this.throwError(`Incompatible combination of dilation_rate with strides.`); + } + + this.activation = activation; + this.activationFunc = activations[activation]; + this.useBias = use_bias; + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel']; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + this.mapInputFragmentsProgram = _WebGL.webgl2.compileProgram(mapInputFragmentsProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0); + } + + super.setWeights(weightsArr, false); + + this._w2row(); + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat; + this.weights['kernel'].createGLTexture({ + type: '2d', + format: 'float' + }); + + if (this.useBias) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + const inputRows = inputShape[0]; + const inputCols = inputShape[1]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + const outputRows = this.padding === 'same' ? Math.floor((inputRows + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputRows - nbRowDilated + this.strides[0]) / this.strides[0]); + const outputCols = this.padding === 'same' ? Math.floor((inputCols + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputCols - nbColDilated + this.strides[1]) / this.strides[1]); + const outputChannels = nbFilter; + const paddingRow = this.padding === 'same' ? Math.max(0, Math.floor((outputRows - 1) * this.strides[0] + nbRowDilated - inputRows)) : 0; + const paddingCol = this.padding === 'same' ? Math.max(0, Math.floor((outputCols - 1) * this.strides[1] + nbColDilated - inputCols)) : 0; + const paddingRowBefore = Math.floor(paddingRow / 2); + const paddingRowAfter = paddingRow - paddingRowBefore; + const paddingColBefore = Math.floor(paddingCol / 2); + const paddingColAfter = paddingCol - paddingColBefore; + this.outputShape = [outputRows, outputCols, outputChannels]; + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]; + } + + _padInput(x, padValue = 0) { + if (this.padding === 'same') { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + const newRows = inputRows + paddingRowBefore + paddingRowAfter; + const newCols = inputCols + paddingColBefore + paddingColAfter; + + const _x = new _Tensor.default([], [newRows, newCols, inputChannels]); + + if (padValue !== 0) { + _ndarrayOps.default.assigns(_x.tensor, padValue); + } + + _ndarrayOps.default.assign(_x.tensor.hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels).lo(paddingRowBefore, paddingColBefore, 0), x.tensor); + + return _x; + } + + return x; + } + + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const nbRow = this.kernelShape[1]; + const nbCol = this.kernelShape[2]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const patchLen = nbRow * nbCol * inputChannels; + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + + if (!this.imColsMat) { + this.imColsMat = new _Tensor.default([], [nbPatches, patchLen]); + } + + if (nbRowDilated === 1 && nbColDilated === 1 && this.strides[0] === 1 && this.strides[1] === 1) { + this.imColsMat.replaceTensorData(x.tensor.data); + return this.imColsMat; + } + + const patch = new _Tensor.default([], [nbRow, nbCol, inputChannels]); + let offset = 0; + + for (let i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbColDilated; j <= limit; j += this.strides[1]) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + nbRowDilated, j + nbColDilated, inputChannels).lo(i, j, 0).step(this.dilationRate[0], this.dilationRate[1], 1)); + + this.imColsMat.tensor.data.set(patch.tensor.data, offset); + offset += patchLen; + } + } + + return this.imColsMat; + } + + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[2]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const patchLen = nbRow * nbCol * inputChannels; + this.wRowsMat = new _Tensor.default([], [patchLen, nbFilter]); + const patch = new _Tensor.default([], [nbRow, nbCol, inputChannels]); + const patchRaveled = new _Tensor.default([], [patchLen]); + + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, null, n)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.wRowsMat.tensor.pick(null, n), patchRaveled.tensor); + } + + return this.wRowsMat; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._im2col(x); + + const nbFilter = this.kernelShape[0]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const matMul = new _Tensor.default([], [nbPatches, nbFilter]); + + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assigns(matMul.tensor.pick(null, n), this.weights['bias'].tensor.get(n)); + } + } + + (0, _ndarrayGemm.default)(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1); + this.output = new _Tensor.default([], this.outputShape); + let outputChannelRaveled = new _Tensor.default([], [outputRows * outputCols]); + let outputChannel = new _Tensor.default([], [outputRows, outputCols]); + + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(outputChannelRaveled.tensor, matMul.tensor.pick(null, n)); + + outputChannel.replaceTensorData(outputChannelRaveled.tensor.data); + + _ndarrayOps.default.assign(this.output.tensor.pick(null, null, n), outputChannel.tensor); + } + + this.activationFunc(this.output); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + let [inputRows, inputCols, inputChannels] = this.inputShape; + let indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + + if (this.padding === 'same') { + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + inputRows = inputRows + paddingRowBefore + paddingRowAfter; + inputCols = inputCols + paddingColBefore + paddingColAfter; + const padValue = -1; + indices = this._padInput(indices, padValue); + } + + const nbRow = this.kernelShape[1]; + const nbCol = this.kernelShape[2]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const patchLen = nbRow * nbCol * inputChannels; + const nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + const nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + this.indexMap = new _Tensor.default([], [nbPatches, patchLen], { + type: Int32Array + }); + const indicesPatch = new _Tensor.default([], [nbRow, nbCol, inputChannels]); + let offset = 0; + + for (let i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbColDilated; j <= limit; j += this.strides[1]) { + _ndarrayOps.default.assign(indicesPatch.tensor, indices.tensor.hi(i + nbRowDilated, j + nbColDilated, inputChannels).lo(i, j, 0).step(this.dilationRate[0], this.dilationRate[1], 1)); + + this.indexMap.tensor.data.set(indicesPatch.tensor.data, offset); + offset += patchLen; + } + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + let outputTextureShape; + + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(x.indicesForReshaped); + + outputTextureShape = [this.indexMap.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } else { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._im2col(x); + + this.imColsMat.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + outputTextureShape = [this.imColsMat.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new _Tensor.default([], outputTextureShape); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputPreactiv.is2DReshaped = true; + this.outputPreactiv.originalShape = this.outputShape; + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (!this.output) { + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (x.is2DReshaped || x.is2DSquareReshaped) { + const hasFragments = Boolean(x.glTextureFragments); + + if (hasFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + } + + if (!this.convProgram) { + const convProgramSource = (0, _createGLSLProgram.default)('conv2d', this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, x.glTextureFragmentShape ? x.glTextureFragmentShape : x.glTextureShape, this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, this.useBias, hasFragments); + this.convProgram = _WebGL.webgl2.compileProgram(convProgramSource); + } + + _WebGL.webgl2.runProgram({ + program: this.convProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }, { + input: this.weights['kernel'], + name: 'kernel' + }, ...(this.useBias ? [{ + input: this.weights['bias'], + name: 'bias' + }] : [])], + supportsTextureFragments: true + }); + + if (hasFragments) { + x.removeGLTextureFragmentsAsColStack(); + } + } else { + const matMulInputs = [{ + input: this.imColsMat, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }]; + + if (this.useBias) { + matMulInputs.push({ + input: this.weights['bias'], + name: 'C' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ + value: this.useBias ? 1 : 0, + type: 'bool', + name: 'addC' + }], + supportsTextureFragments: true + }); + } + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + +} + +exports.default = Conv2D; \ No newline at end of file diff --git a/lib/layers/convolutional/Conv2DTranspose.js b/lib/layers/convolutional/Conv2DTranspose.js new file mode 100644 index 0000000000..4a91d95b1c --- /dev/null +++ b/lib/layers/convolutional/Conv2DTranspose.js @@ -0,0 +1,471 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _cwise = _interopRequireDefault(require("cwise")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; +const assignToRowIndicesMap = (0, _cwise.default)({ + args: [{ + blockIndices: -1 + }, 'scalar', 'scalar'], + body: function (x, rowIndex, size) { + for (let i = 0; i < size; i++) { + if (x[i] === -1) { + x[i] = rowIndex; + break; + } + } + } +}); +const assignToColIndicesMap = (0, _cwise.default)({ + args: [{ + blockIndices: -1 + }, 'array', 'scalar'], + body: function (x, colIndex, size) { + for (let i = 0; i < size; i++) { + if (x[i] === -1) { + x[i] = colIndex; + break; + } + } + } +}); + +class Conv2DTranspose extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Conv2DTranspose'; + const { + filters = 1, + kernel_size = [3, 3], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + activation = 'linear', + use_bias = true + } = attrs; + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size]; + } else { + this.kernelShape = [filters, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else { + this.strides = [strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format; + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + this.activation = activation; + this.activationFunc = activations[activation]; + this.useBias = use_bias; + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel']; + + if (this.gpu) { + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0); + } + + super.setWeights(weightsArr, false); + + this._w2row(); + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat; + this.weights['kernel'].createGLTexture({ + type: '2d', + format: 'float' + }); + + if (this.useBias) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.outputPadding) { + return; + } + + const inputRows = inputShape[0]; + const inputCols = inputShape[1]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const outputRows = this.padding === 'same' ? inputRows * this.strides[0] : inputRows * this.strides[0] + Math.max(nbRow - this.strides[0], 0); + const outputCols = this.padding === 'same' ? inputCols * this.strides[1] : inputCols * this.strides[1] + Math.max(nbCol - this.strides[1], 0); + const outputChannels = nbFilter; + const paddingRow = this.padding === 'same' ? Math.max(0, Math.floor((inputRows - 1) * this.strides[0] + nbRow - outputRows)) : 0; + const paddingCol = this.padding === 'same' ? Math.max(0, Math.floor((inputCols - 1) * this.strides[1] + nbCol - outputCols)) : 0; + const paddingRowBefore = Math.floor(paddingRow / 2); + const paddingRowAfter = paddingRow - paddingRowBefore; + const paddingColBefore = Math.floor(paddingCol / 2); + const paddingColAfter = paddingCol - paddingColBefore; + this.outputShape = [outputRows, outputCols, outputChannels]; + this.outputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]; + } + + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + + if (!this.imColsMat) { + this.imColsMat = new _Tensor.default([], [inputRows * inputCols, inputChannels]); + } + + const channelRaveled = new _Tensor.default([], [inputRows * inputCols]); + const channel = new _Tensor.default([], [inputRows, inputCols]); + + for (let c = 0; c < inputChannels; c++) { + _ndarrayOps.default.assign(channel.tensor, x.tensor.pick(null, null, c)); + + channelRaveled.replaceTensorData(channel.tensor.data); + + _ndarrayOps.default.assign(this.imColsMat.tensor.pick(null, c), channelRaveled.tensor); + } + + return this.imColsMat; + } + + _w2row() { + const [nbRow, nbCol, nbFilter, inputChannels] = this.weights['kernel'].tensor.shape; + this.wRowsMat = new _Tensor.default([], [inputChannels, nbRow * nbCol * nbFilter]); + const channelRaveled = new _Tensor.default([], [nbRow * nbCol * nbFilter]); + const channel = new _Tensor.default([], [nbRow, nbCol, nbFilter]); + + for (let c = 0; c < inputChannels; c++) { + _ndarrayOps.default.assign(channel.tensor, this.weights['kernel'].tensor.pick(null, null, null, c)); + + channelRaveled.replaceTensorData(channel.tensor.data); + + _ndarrayOps.default.assign(this.wRowsMat.tensor.pick(c, null), channelRaveled.tensor); + } + + return this.wRowsMat; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + this._im2col(x); + + const inputRows = x.tensor.shape[0]; + const inputCols = x.tensor.shape[1]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const matMul = new _Tensor.default([], [inputRows * inputCols, nbRow * nbCol * nbFilter]); + (0, _ndarrayGemm.default)(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1); + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.outputPadding; + this.output = new _Tensor.default([], this.outputShape); + let outputPadded = new _Tensor.default([], [this.outputShape[0] + paddingRowBefore + paddingRowAfter, this.outputShape[1] + paddingColBefore + paddingColAfter, this.outputShape[2]]); + const patchShape = [nbRow, nbCol, nbFilter]; + let patch = new _Tensor.default([], patchShape); + let patchRaveled = new _Tensor.default([], [nbRow * nbCol * nbFilter]); + let index = 0; + + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + _ndarrayOps.default.assign(patchRaveled.tensor, matMul.tensor.pick(index, null)); + + patch.replaceTensorData(patchRaveled.tensor.data); + const iOutPos = i * this.strides[0]; + const jOutPos = j * this.strides[1]; + + _ndarrayOps.default.addeq(outputPadded.tensor.hi(iOutPos + nbRow, jOutPos + nbCol, this.outputShape[2]).lo(iOutPos, jOutPos, 0), patch.tensor); + + index += 1; + } + } + + _ndarrayOps.default.assign(this.output.tensor, outputPadded.tensor.hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, this.outputShape[2]).lo(paddingRowBefore, paddingColBefore, 0)); + + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.addseq(this.output.tensor.pick(null, null, n), this.weights['bias'].tensor.get(n)); + } + } + + this.activationFunc(this.output); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const inputRows = this.inputShape[0]; + const inputCols = this.inputShape[1]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.outputPadding; + const effectiveKernelSize = (nbRow - this.strides[0] + 1) * (nbCol - this.strides[1] + 1); + const indicesMapShape = [this.outputShape[0], this.outputShape[1], effectiveKernelSize]; + const indicesMapShapePadded = [this.outputShape[0] + paddingRowBefore + paddingRowAfter, this.outputShape[1] + paddingColBefore + paddingColAfter, effectiveKernelSize]; + const outputRowIndicesMap = new _Tensor.default([], indicesMapShape, { + type: Int32Array + }); + const outputColIndicesMap = new _Tensor.default([], indicesMapShape, { + type: Int32Array + }); + const outputRowIndicesMapPadded = new _Tensor.default([], indicesMapShapePadded, { + type: Int32Array + }); + const outputColIndicesMapPadded = new _Tensor.default([], indicesMapShapePadded, { + type: Int32Array + }); + + _ndarrayOps.default.assigns(outputRowIndicesMap.tensor, -1); + + _ndarrayOps.default.assigns(outputColIndicesMap.tensor, -1); + + _ndarrayOps.default.assigns(outputRowIndicesMapPadded.tensor, -1); + + _ndarrayOps.default.assigns(outputColIndicesMapPadded.tensor, -1); + + const matMulColIndicesPatch = new _Tensor.default([], [nbRow, nbCol, nbFilter], { + type: Int32Array + }); + + for (let i = 0; i < nbRow * nbCol * nbFilter; i++) { + matMulColIndicesPatch.tensor.data[i] = i; + } + + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + const matMulRowIndex = i * inputCols + j; + const iOutPos = i * this.strides[0]; + const jOutPos = j * this.strides[1]; + assignToRowIndicesMap(outputRowIndicesMapPadded.tensor.hi(iOutPos + nbRow, jOutPos + nbCol, effectiveKernelSize).lo(iOutPos, jOutPos, 0), matMulRowIndex, effectiveKernelSize); + assignToColIndicesMap(outputColIndicesMapPadded.tensor.hi(iOutPos + nbRow, jOutPos + nbCol, effectiveKernelSize).lo(iOutPos, jOutPos, 0), matMulColIndicesPatch.tensor.pick(null, null, 0), effectiveKernelSize); + } + } + + _ndarrayOps.default.assign(outputRowIndicesMap.tensor, outputRowIndicesMapPadded.tensor.hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, effectiveKernelSize).lo(paddingRowBefore, paddingColBefore, 0)); + + _ndarrayOps.default.assign(outputColIndicesMap.tensor, outputColIndicesMapPadded.tensor.hi(this.outputShape[0] + paddingRowBefore, this.outputShape[1] + paddingColBefore, effectiveKernelSize).lo(paddingRowBefore, paddingColBefore, 0)); + + const tiledIndicesMapShape = [this.outputShape[0] * this.outputShape[1], effectiveKernelSize]; + this.indexMap = new _Tensor.default([], tiledIndicesMapShape, { + type: Int32Array + }); + const channelData = new _Tensor.default([], [effectiveKernelSize], { + type: Int32Array + }); + + for (let i = 0; i < this.outputShape[0]; i++) { + for (let j = 0; j < this.outputShape[1]; j++) { + for (let k = 0; k < effectiveKernelSize; k++) { + const rowIndex = outputRowIndicesMap.tensor.get(i, j, k); + const colIndex = outputColIndicesMap.tensor.get(i, j, k); + + if (rowIndex !== -1 && colIndex !== -1) { + channelData.tensor.set(k, rowIndex * this.weights['kernel'].glTextureShape[1] + colIndex); + } else { + channelData.tensor.set(k, -1); + } + } + + _ndarrayOps.default.assign(this.indexMap.tensor.pick(i * this.outputShape[1] + j, null), channelData.tensor); + } + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + + this._calcOutputShape(this.inputShape); + } else { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + this._im2col(x); + + this.imColsMat.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.imColsMat; + + if (!this.matMulResult) { + const outputTextureShape = [input.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + this.matMulResult = new _Tensor.default([], outputTextureShape); + this.matMulResult.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + const outputTextureShape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]]; + this.outputPreactiv = new _Tensor.default([], outputTextureShape); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputPreactiv.is2DReshaped = true; + this.outputPreactiv.originalShape = this.outputShape; + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (!this.output) { + const outputTextureShape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]]; + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.matMulResult, + inputs: [{ + input: input, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }], + supportsTextureFragments: true + }); + + this._createIndexMap(); + + const hasFragments = Boolean(this.matMulResult.glTextureFragments); + + if (hasFragments) { + this.matMulResult.convert2DRowFragmentedGLTextureToColStack(); + } + + if (!this.convTransposeProgram) { + const convTransposeProgramSource = (0, _createGLSLProgram.default)('conv2dTranspose', this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, this.matMulResult.glTextureFragmentShape ? this.matMulResult.glTextureFragmentShape : this.matMulResult.glTextureShape, this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, this.useBias, hasFragments); + this.convTransposeProgram = _WebGL.webgl2.compileProgram(convTransposeProgramSource); + } + + _WebGL.webgl2.runProgram({ + program: this.convTransposeProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [{ + input: this.matMulResult, + name: 'matMulResult' + }, { + input: this.indexMap, + name: 'indexMap' + }, ...(this.useBias ? [{ + input: this.weights['bias'], + name: 'bias' + }] : [])], + supportsTextureFragments: true + }); + + if (hasFragments) { + this.matMulResult.removeGLTextureFragmentsAsColStack(); + } + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + +} + +exports.default = Conv2DTranspose; \ No newline at end of file diff --git a/lib/layers/convolutional/Conv3D.js b/lib/layers/convolutional/Conv3D.js new file mode 100644 index 0000000000..50c83a0686 --- /dev/null +++ b/lib/layers/convolutional/Conv3D.js @@ -0,0 +1,476 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const mapInputFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(indexMap, 0);\r\n int out_x = int(float(outputSize[0]) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n int fragmentIndex = int(floor(float(rowIndex) / float(inputSize[1])));\r\n rowIndex = int(mod(float(rowIndex), float(inputSize[1])));\r\n colIndex = fragmentIndex * inputCols + colIndex;\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class Conv3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Conv3D'; + const { + filters = 1, + kernel_size = [1, 1, 1], + strides = [1, 1, 1], + padding = 'valid', + data_format = 'channels_last', + dilation_rate = [1, 1, 1], + activation = 'linear', + use_bias = true + } = attrs; + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size]; + } else { + this.kernelShape = [filters, kernel_size, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else { + this.strides = [strides, strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format; + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + if (Array.isArray(dilation_rate)) { + this.dilationRate = dilation_rate; + } else { + this.dilationRate = [dilation_rate, dilation_rate, dilation_rate]; + } + + if ((this.dilationRate[0] !== 1 || this.dilationRate[1] !== 1 || this.dilationRate[2] !== 1) && (this.strides[0] !== 1 || this.strides[1] !== 1 || this.strides[2] !== 1)) { + this.throwError('Incompatible combination of dilation_rate with strides.'); + } + + this.activation = activation; + this.activationFunc = activations[activation]; + this.useBias = use_bias; + this.params = this.useBias ? ['kernel', 'bias'] : ['kernel']; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + this.mapInputFragmentsProgram = _WebGL.webgl2.compileProgram(mapInputFragmentsProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 4, 1, 0); + } + + super.setWeights(weightsArr, false); + + this._w2row(); + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat; + this.weights['kernel'].createGLTexture({ + type: '2d', + format: 'float' + }); + + if (this.useBias) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + const inputDim1 = inputShape[0]; + const inputDim2 = inputShape[1]; + const inputDim3 = inputShape[2]; + const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape; + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1); + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1); + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1); + const outputDim1 = this.padding === 'same' ? Math.floor((inputDim1 + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputDim1 - kernelDim1Dilated + this.strides[0]) / this.strides[0]); + const outputDim2 = this.padding === 'same' ? Math.floor((inputDim2 + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputDim2 - kernelDim2Dilated + this.strides[1]) / this.strides[1]); + const outputDim3 = this.padding === 'same' ? Math.floor((inputDim3 + this.strides[2] - 1) / this.strides[2]) : Math.floor((inputDim3 - kernelDim3Dilated + this.strides[2]) / this.strides[2]); + const outputChannels = nbFilter; + const paddingDim1 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim1 - 1) * this.strides[0] + kernelDim1Dilated - inputDim1)) : 0; + const paddingDim2 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim2 - 1) * this.strides[1] + kernelDim2Dilated - inputDim2)) : 0; + const paddingDim3 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim3 - 1) * this.strides[2] + kernelDim3Dilated - inputDim3)) : 0; + const paddingDim1Before = Math.floor(paddingDim1 / 2); + const paddingDim1After = paddingDim1 - paddingDim1Before; + const paddingDim2Before = Math.floor(paddingDim2 / 2); + const paddingDim2After = paddingDim2 - paddingDim2Before; + const paddingDim3Before = Math.floor(paddingDim3 / 2); + const paddingDim3After = paddingDim3 - paddingDim3Before; + this.outputShape = [outputDim1, outputDim2, outputDim3, outputChannels]; + this.inputPadding = [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After]; + } + + _padInput(x, padValue = 0) { + if (this.padding === 'same') { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + const newDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + const newDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + const newDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + + const _x = new _Tensor.default([], [newDim1, newDim2, newDim3, inputChannels]); + + if (padValue !== 0) { + _ndarrayOps.default.assigns(_x.tensor, padValue); + } + + _ndarrayOps.default.assign(_x.tensor.hi(inputDim1 + paddingDim1Before, inputDim2 + paddingDim2Before, inputDim3 + paddingDim3Before, inputChannels).lo(paddingDim1Before, paddingDim2Before, paddingDim3Before, 0), x.tensor); + + return _x; + } + + return x; + } + + _vol2col(x) { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + const kernelDim1 = this.kernelShape[1]; + const kernelDim2 = this.kernelShape[2]; + const kernelDim3 = this.kernelShape[3]; + const outputDim1 = this.outputShape[0]; + const outputDim2 = this.outputShape[1]; + const outputDim3 = this.outputShape[2]; + const nbPatches = outputDim1 * outputDim2 * outputDim3; + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels; + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1); + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1); + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1); + + if (!this.volColsMat) { + this.volColsMat = new _Tensor.default([], [nbPatches, patchLen]); + } + + if (kernelDim1Dilated === 1 && kernelDim2Dilated === 1 && kernelDim3Dilated === 1 && this.strides[0] === 1 && this.strides[1] === 1 && this.strides[2] === 1) { + this.volColsMat.replaceTensorData(x.tensor.data); + return this.volColsMat; + } + + const patch = new _Tensor.default([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]); + let offset = 0; + + for (let i = 0, limit = inputDim1 - kernelDim1Dilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - kernelDim2Dilated; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - kernelDim3Dilated; k <= limit; k += this.strides[2]) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + kernelDim1Dilated, j + kernelDim2Dilated, k + kernelDim3Dilated, inputChannels).lo(i, j, k, 0).step(this.dilationRate[0], this.dilationRate[1], this.dilationRate[2], 1)); + + this.volColsMat.tensor.data.set(patch.tensor.data, offset); + offset += patchLen; + } + } + } + + return this.volColsMat; + } + + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[3]; + const [nbFilter, kernelDim1, kernelDim2, kernelDim3] = this.kernelShape; + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels; + this.wRowsMat = new _Tensor.default([], [patchLen, nbFilter]); + const patch = new _Tensor.default([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]); + const patchRaveled = new _Tensor.default([], [patchLen]); + + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, null, null, n)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.wRowsMat.tensor.pick(null, n), patchRaveled.tensor); + } + + return this.wRowsMat; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._vol2col(x); + + const nbFilter = this.kernelShape[0]; + const outputDim1 = this.outputShape[0]; + const outputDim2 = this.outputShape[1]; + const outputDim3 = this.outputShape[2]; + const nbPatches = outputDim1 * outputDim2 * outputDim3; + const matMul = new _Tensor.default([], [nbPatches, nbFilter]); + + if (this.useBias) { + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assigns(matMul.tensor.pick(null, n), this.weights['bias'].tensor.get(n)); + } + } + + (0, _ndarrayGemm.default)(matMul.tensor, this.volColsMat.tensor, this.wRowsMat.tensor, 1, 1); + this.output = new _Tensor.default([], this.outputShape); + let outputChannelRaveled = new _Tensor.default([], [outputDim1 * outputDim2 * outputDim3]); + let outputChannel = new _Tensor.default([], [outputDim1, outputDim2, outputDim3]); + + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(outputChannelRaveled.tensor, matMul.tensor.pick(null, n)); + + outputChannel.replaceTensorData(outputChannelRaveled.tensor.data); + + _ndarrayOps.default.assign(this.output.tensor.pick(null, null, null, n), outputChannel.tensor); + } + + this.activationFunc(this.output); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + let [inputDim1, inputDim2, inputDim3, inputChannels] = this.inputShape; + let indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + + if (this.padding === 'same') { + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + inputDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + inputDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + inputDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + const padValue = -1; + indices = this._padInput(indices, padValue); + } + + const kernelDim1 = this.kernelShape[1]; + const kernelDim2 = this.kernelShape[2]; + const kernelDim3 = this.kernelShape[3]; + const outputDim1 = this.outputShape[0]; + const outputDim2 = this.outputShape[1]; + const outputDim3 = this.outputShape[2]; + const nbPatches = outputDim1 * outputDim2 * outputDim3; + const patchLen = kernelDim1 * kernelDim2 * kernelDim3 * inputChannels; + const kernelDim1Dilated = kernelDim1 + (kernelDim1 - 1) * (this.dilationRate[0] - 1); + const kernelDim2Dilated = kernelDim2 + (kernelDim2 - 1) * (this.dilationRate[1] - 1); + const kernelDim3Dilated = kernelDim3 + (kernelDim3 - 1) * (this.dilationRate[2] - 1); + this.indexMap = new _Tensor.default([], [nbPatches, patchLen], { + type: Int32Array + }); + const indicesPatch = new _Tensor.default([], [kernelDim1, kernelDim2, kernelDim3, inputChannels]); + let offset = 0; + + for (let i = 0, limit = inputDim1 - kernelDim1Dilated; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - kernelDim2Dilated; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - kernelDim3Dilated; k <= limit; k += this.strides[2]) { + _ndarrayOps.default.assign(indicesPatch.tensor, indices.tensor.hi(i + kernelDim1Dilated, j + kernelDim2Dilated, k + kernelDim3Dilated, inputChannels).lo(i, j, k, 0).step(this.dilationRate[0], this.dilationRate[1], this.dilationRate[2], 1)); + + this.indexMap.tensor.data.set(indicesPatch.tensor.data, offset); + offset += patchLen; + } + } + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + let outputTextureShape; + + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(x.indicesForReshaped); + + outputTextureShape = [this.indexMap.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } else { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._vol2col(x); + + this.volColsMat.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + outputTextureShape = [this.volColsMat.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new _Tensor.default([], outputTextureShape); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputPreactiv.is2DReshaped = true; + this.outputPreactiv.originalShape = this.outputShape; + this.outputPreactiv.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (!this.output) { + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (x.is2DReshaped || x.is2DSquareReshaped) { + const hasFragments = Boolean(x.glTextureFragments); + + if (hasFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + } + + if (!this.convProgram) { + const convProgramSource = (0, _createGLSLProgram.default)('conv2d', this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, x.glTextureFragmentShape ? x.glTextureFragmentShape : x.glTextureShape, this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, this.useBias, hasFragments); + this.convProgram = _WebGL.webgl2.compileProgram(convProgramSource); + } + + _WebGL.webgl2.runProgram({ + program: this.convProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }, { + input: this.weights['kernel'], + name: 'kernel' + }, ...(this.useBias ? [{ + input: this.weights['bias'], + name: 'bias' + }] : [])], + supportsTextureFragments: true + }); + + if (hasFragments) { + x.removeGLTextureFragmentsAsColStack(); + } + } else { + const matMulInputs = [{ + input: this.volColsMat, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }]; + + if (this.useBias) { + matMulInputs.push({ + input: this.weights['bias'], + name: 'C' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ + value: this.useBias ? 1 : 0, + type: 'bool', + name: 'addC' + }], + supportsTextureFragments: true + }); + } + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + } + +} + +exports.default = Conv3D; \ No newline at end of file diff --git a/lib/layers/convolutional/Cropping1D.js b/lib/layers/convolutional/Cropping1D.js new file mode 100644 index 0000000000..15d96ade58 --- /dev/null +++ b/lib/layers/convolutional/Cropping1D.js @@ -0,0 +1,143 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Cropping1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Cropping1D'; + const { + cropping = [0, 0] + } = attrs; + + if (Array.isArray(cropping)) { + this.cropping = cropping; + } else { + this.cropping = [cropping, cropping]; + } + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] - this.cropping[0] - this.cropping[1], this.inputShape[1]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor, x.tensor.hi(this.inputShape[0] - this.cropping[1], this.inputShape[2]).lo(this.cropping[0], 0)); + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(null, j), j); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = [this.cropping[0], 0]; + const sliceEnd = [this.inputShape[0] - this.cropping[1], this.inputShape[2]]; + + _ndarrayOps.default.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)); + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] - this.cropping[0] - this.cropping[1], this.inputShape[1]]; + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Cropping1D; \ No newline at end of file diff --git a/lib/layers/convolutional/Cropping2D.js b/lib/layers/convolutional/Cropping2D.js new file mode 100644 index 0000000000..eb9825d794 --- /dev/null +++ b/lib/layers/convolutional/Cropping2D.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Cropping2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Cropping2D'; + const { + cropping = [[0, 0], [0, 0]], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(cropping)) { + if (Array.isArray(cropping[0])) { + this.cropping = cropping; + } else { + this.cropping = [[cropping[0], cropping[0]], [cropping[1], cropping[1]]]; + } + } else { + this.cropping = [[cropping, cropping], [cropping, cropping]]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[2]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor, x.tensor.hi(this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2]).lo(this.cropping[0][0], this.cropping[1][0], 0)); + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1); + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = this.dataFormat === 'channels_first' ? [0, this.cropping[0][0], this.cropping[1][0]] : [this.cropping[0][0], this.cropping[1][0], 0]; + const sliceEnd = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][1]] : [this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2]]; + + _ndarrayOps.default.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)); + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][0] - this.cropping[1][1]] : [this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[2]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = Cropping2D; \ No newline at end of file diff --git a/lib/layers/convolutional/Cropping3D.js b/lib/layers/convolutional/Cropping3D.js new file mode 100644 index 0000000000..a28b472fa8 --- /dev/null +++ b/lib/layers/convolutional/Cropping3D.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Cropping3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Cropping3D'; + const { + cropping = [[0, 0], [0, 0], [0, 0]], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(cropping)) { + if (Array.isArray(cropping[0])) { + this.cropping = cropping; + } else { + this.cropping = [[cropping[0], cropping[0]], [cropping[1], cropping[1]], [cropping[2], cropping[2]]]; + } + } else { + this.cropping = [[cropping, cropping], [cropping, cropping], [cropping, cropping]]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[2] - this.cropping[2][0] - this.cropping[2][1], this.inputShape[3]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor, x.tensor.hi(this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2] - this.cropping[2][1], this.inputShape[3]).lo(this.cropping[0][0], this.cropping[1][0], this.cropping[2][0], 0)); + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2); + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = this.dataFormat === 'channels_first' ? [0, this.cropping[0][0], this.cropping[1][0], this.cropping[2][0]] : [this.cropping[0][0], this.cropping[1][0], this.cropping[2][0], 0]; + const sliceEnd = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][1], this.inputShape[3] - this.cropping[2][1]] : [this.inputShape[0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][1], this.inputShape[2] - this.cropping[2][1], this.inputShape[3]]; + + _ndarrayOps.default.assign(this.indexMap.tensor, indices.tensor.hi(...sliceEnd).lo(...sliceStart)); + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[2] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[3] - this.cropping[2][0] - this.cropping[2][1]] : [this.inputShape[0] - this.cropping[0][0] - this.cropping[0][1], this.inputShape[1] - this.cropping[1][0] - this.cropping[1][1], this.inputShape[2] - this.cropping[2][0] - this.cropping[2][1], this.inputShape[3]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = Cropping3D; \ No newline at end of file diff --git a/lib/layers/convolutional/SeparableConv2D.js b/lib/layers/convolutional/SeparableConv2D.js new file mode 100644 index 0000000000..1b557064c8 --- /dev/null +++ b/lib/layers/convolutional/SeparableConv2D.js @@ -0,0 +1,366 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var _Conv2D = _interopRequireDefault(require("./Conv2D")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class _DepthwiseConv2D extends _Conv2D.default { + constructor(attrs = {}) { + super(attrs); + } + + _calcOutputShape(inputShape) { + super._calcOutputShape(inputShape); + + const nbFilter = this.kernelShape[0]; + const inputChannels = inputShape[2]; + this.outputShape[2] = nbFilter * inputChannels; + } + + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const nbRow = this.kernelShape[1]; + const nbCol = this.kernelShape[2]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const patchLen = nbRow * nbCol; + + if (!this.imColsMat) { + this.imColsMat = new _Tensor.default([], [nbPatches * inputChannels, patchLen]); + } + + let patch = new _Tensor.default([], [nbRow, nbCol, 1]); + let offset = 0; + + for (let c = 0; c < inputChannels; c++) { + for (let i = 0, limit = inputRows - nbRow; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbCol; j <= limit; j += this.strides[1]) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + nbRow, j + nbCol, c + 1).lo(i, j, c)); + + this.imColsMat.tensor.data.set(patch.tensor.data, offset); + offset += patchLen; + } + } + } + + return this.imColsMat; + } + + _w2row() { + const inputChannels = this.weights['kernel'].tensor.shape[2]; + const [nbFilter, nbRow, nbCol] = this.kernelShape; + const patchLen = nbRow * nbCol; + this.wRowsMat = new _Tensor.default([], [patchLen, nbFilter * inputChannels]); + let patch = new _Tensor.default([], [nbRow, nbCol]); + let patchRaveled = new _Tensor.default([], [patchLen]); + let p = 0; + + for (let c = 0; c < inputChannels; c++) { + for (let n = 0; n < nbFilter; n++) { + _ndarrayOps.default.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, c, n)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.wRowsMat.tensor.pick(null, p), patchRaveled.tensor); + + p += 1; + } + } + + return this.wRowsMat; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._im2col(x); + + const nbFilter = this.kernelShape[0]; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + const nbPatches = outputRows * outputCols; + const inputChannels = this.inputShape[2]; + const matMul = new _Tensor.default([], [nbPatches * inputChannels, nbFilter * inputChannels]); + (0, _ndarrayGemm.default)(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1); + this.output = new _Tensor.default([], this.outputShape); + const outputDataLength = outputRows * outputCols * nbFilter * inputChannels; + let dataFiltered = new Float32Array(outputDataLength); + + for (let c = 0; c < inputChannels; c++) { + for (let n = c * outputDataLength + c * nbFilter; n < (c + 1) * outputDataLength; n += nbFilter * inputChannels) { + for (let m = 0; m < nbFilter; m++) { + dataFiltered[n + m - c * outputDataLength] = matMul.tensor.data[n + m]; + } + } + } + + this.output.replaceTensorData(dataFiltered); + } + + _createOutputReshapeIndexMap() { + if (this.reshapeIndexMap) { + return; + } + + const nbFilter = this.kernelShape[0]; + const reshape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]]; + const reshapeRowIndices = new _Tensor.default([], reshape, { + type: Int32Array + }); + const reshapeColIndices = new _Tensor.default([], reshape, { + type: Int32Array + }); + this.reshapeIndexMap = new _Tensor.default([], reshape, { + type: Int32Array + }); + + for (let j = 0; j < reshape[1]; j++) { + for (let i = 0; i < reshape[0]; i++) { + _ndarrayOps.default.assigns(reshapeRowIndices.tensor.pick(i, j), i + Math.floor(j / nbFilter) * reshape[0]); + } + } + + for (let j = 0; j < reshape[1]; j++) { + _ndarrayOps.default.assigns(reshapeColIndices.tensor.pick(null, j), j); + } + + _ndarrayOps.default.muls(this.reshapeIndexMap.tensor, reshapeRowIndices.tensor, reshape[1]); + + _ndarrayOps.default.addeq(this.reshapeIndexMap.tensor, reshapeColIndices.tensor); + + this.reshapeIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + super._callGPU(x); + + this._createOutputReshapeIndexMap(); + + if (!this.outputReshaped) { + const reshape = [this.outputShape[0] * this.outputShape[1], this.outputShape[2]]; + this.outputReshaped = new _Tensor.default([], reshape); + this.outputReshaped.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputReshaped.is2DReshaped = true; + this.outputReshaped.originalShape = this.outputShape; + this.outputReshaped.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + if (this.output.glTextureFragments) { + this.output.convert2DRowFragmentedGLTextureToColStack(); + } + + _WebGL.webgl2.runProgram({ + program: this.output.glTextureFragments ? this.mapInputFragmentsProgram : this.mapInputProgram, + output: this.outputReshaped, + inputs: [{ + input: this.output, + name: 'x' + }, { + input: this.reshapeIndexMap, + name: 'indexMap' + }], + uniforms: [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'inputCols' + }], + supportsTextureFragments: true + }); + + if (this.output.glTextureFragments) { + this.output.removeGLTextureFragmentsAsColStack(); + } + } + +} + +class SeparableConv2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'SeparableConv2D'; + const { + filters = 1, + kernel_size = [1, 1], + strides = [1, 1], + padding = 'valid', + data_format = 'channels_last', + depth_multiplier = 1, + activation = 'linear', + use_bias = true + } = attrs; + + if (Array.isArray(kernel_size)) { + this.kernelShape = [filters, ...kernel_size]; + } else { + this.kernelShape = [filters, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else { + this.strides = [strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + this.dataFormat = data_format; + } else { + this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + this.activation = activation; + this.activationFunc = activations[activation]; + + if (padding === 'valid' || padding === 'same') { + this.padding = padding; + } else { + this.throwError('Invalid padding.'); + } + + this.useBias = use_bias; + this.params = this.useBias ? ['depthwise_kernel', 'pointwise_kernel', 'bias'] : ['depthwise_kernel', 'pointwise_kernel']; + this.depthwiseConvAttrs = { + filters: depth_multiplier, + kernel_size: [this.kernelShape[1], this.kernelShape[2]], + strides: this.strides, + padding, + data_format, + activation: 'linear', + use_bias: false, + gpu: attrs.gpu + }; + this.pointwiseConvAttrs = { + filters, + kernel_size: [1, 1], + strides: [1, 1], + padding, + data_format, + activation: 'linear', + use_bias, + gpu: attrs.gpu + }; + + if (this.gpu) { + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + setWeights(weightsArr) { + this._depthwiseConv = new _DepthwiseConv2D(this.depthwiseConvAttrs); + + this._depthwiseConv.setWeights(weightsArr.slice(0, 1)); + + this._pointwiseConv = new _Conv2D.default(this.pointwiseConvAttrs); + + this._pointwiseConv.setWeights(weightsArr.slice(1, 3)); + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this._depthwiseConv._callCPU(x); + + this._pointwiseConv._callCPU(this._depthwiseConv.output); + + this.output = this._pointwiseConv.output; + this.activationFunc(this.output); + } + + _callGPU(x) { + this._depthwiseConv.outbound = [null]; + this._pointwiseConv.outbound = [null]; + + this._depthwiseConv._callGPU(x); + + this._pointwiseConv._callGPU(this._depthwiseConv.outputReshaped); + + if (this.activation === 'linear') { + this.output = this._pointwiseConv.output; + } else { + if (!this.output) { + this.output = new _Tensor.default([], this._pointwiseConv.output.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this._pointwiseConv.output.originalShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this._pointwiseConv.output.originalShape, false, -1); + } + + this.outputPreactiv = this._pointwiseConv.output; + + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + +} + +exports.default = SeparableConv2D; \ No newline at end of file diff --git a/lib/layers/convolutional/UpSampling1D.js b/lib/layers/convolutional/UpSampling1D.js new file mode 100644 index 0000000000..eda598eebf --- /dev/null +++ b/lib/layers/convolutional/UpSampling1D.js @@ -0,0 +1,140 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class UpSampling1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'UpSampling1D'; + const { + size = 2 + } = attrs; + this.size = size; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] * this.size, this.inputShape[1]]; + this.output = new _Tensor.default([], this.outputShape); + + for (let i = 0; i < this.size; i++) { + _ndarrayOps.default.assign(this.output.tensor.lo(i, 0).step(this.size, 1), x.tensor); + } + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(null, j), j); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.size; i++) { + _ndarrayOps.default.assign(this.indexMap.tensor.lo(i, 0).step(this.size, 1), indices.tensor); + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] * this.size, this.inputShape[1]]; + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = UpSampling1D; \ No newline at end of file diff --git a/lib/layers/convolutional/UpSampling2D.js b/lib/layers/convolutional/UpSampling2D.js new file mode 100644 index 0000000000..bd032d24a8 --- /dev/null +++ b/lib/layers/convolutional/UpSampling2D.js @@ -0,0 +1,149 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class UpSampling2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'UpSampling2D'; + const { + size = [2, 2], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(size)) { + this.size = size; + } else { + this.size = [size, size]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2]]; + this.output = new _Tensor.default([], this.outputShape); + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + _ndarrayOps.default.assign(this.output.tensor.lo(i, j, 0).step(this.size[0], this.size[1], 1), x.tensor); + } + } + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1); + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + const sliceStart = this.dataFormat === 'channels_first' ? [0, i, j] : [i, j, 0]; + const step = this.dataFormat === 'channels_first' ? [1, this.size[0], this.size[1]] : [this.size[0], this.size[1], 1]; + + _ndarrayOps.default.assign(this.indexMap.tensor.lo(...sliceStart).step(...step), indices.tensor); + } + } + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] * this.size[0], this.inputShape[2] * this.size[1]] : [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = UpSampling2D; \ No newline at end of file diff --git a/lib/layers/convolutional/UpSampling3D.js b/lib/layers/convolutional/UpSampling3D.js new file mode 100644 index 0000000000..9ea2cd274e --- /dev/null +++ b/lib/layers/convolutional/UpSampling3D.js @@ -0,0 +1,153 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class UpSampling3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'UpSampling3D'; + const { + size = [2, 2, 2], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(size)) { + this.size = size; + } else { + this.size = [size, size, size]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2] * this.size[2], this.inputShape[3]]; + this.output = new _Tensor.default([], this.outputShape); + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + for (let k = 0; k < this.size[2]; k++) { + _ndarrayOps.default.assign(this.output.tensor.lo(i, j, k, 0).step(this.size[0], this.size[1], this.size[2], 1), x.tensor); + } + } + } + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2); + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.size[0]; i++) { + for (let j = 0; j < this.size[1]; j++) { + for (let k = 0; k < this.size[2]; k++) { + const sliceStart = this.dataFormat === 'channels_first' ? [0, i, j, k] : [i, j, k, 0]; + const step = this.dataFormat === 'channels_first' ? [1, this.size[0], this.size[1], this.size[2]] : [this.size[0], this.size[1], this.size[2], 1]; + + _ndarrayOps.default.assign(this.indexMap.tensor.lo(...sliceStart).step(...step), indices.tensor); + } + } + } + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] * this.size[0], this.inputShape[2] * this.size[1], this.inputShape[3] * this.size[2]] : [this.inputShape[0] * this.size[0], this.inputShape[1] * this.size[1], this.inputShape[2] * this.size[2], this.inputShape[3]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = UpSampling3D; \ No newline at end of file diff --git a/lib/layers/convolutional/ZeroPadding1D.js b/lib/layers/convolutional/ZeroPadding1D.js new file mode 100644 index 0000000000..62c841cce0 --- /dev/null +++ b/lib/layers/convolutional/ZeroPadding1D.js @@ -0,0 +1,145 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class ZeroPadding1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'ZeroPadding1D'; + const { + padding = [1, 1] + } = attrs; + + if (Array.isArray(padding)) { + this.padding = padding; + } else { + this.padding = [padding, padding]; + } + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] + this.padding[0] + this.padding[1], this.inputShape[1]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor.hi(this.inputShape[0] + this.padding[0], this.inputShape[1]).lo(this.padding[0], 0), x.tensor); + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(null, j), j); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, this.inputShape[1]); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = [this.padding[0], 0]; + const sliceEnd = [this.inputShape[0] + this.padding[0], this.inputShape[1]]; + + _ndarrayOps.default.assigns(this.indexMap.tensor, -1); + + _ndarrayOps.default.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor); + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] + this.padding[0] + this.padding[1], this.inputShape[1]]; + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = ZeroPadding1D; \ No newline at end of file diff --git a/lib/layers/convolutional/ZeroPadding2D.js b/lib/layers/convolutional/ZeroPadding2D.js new file mode 100644 index 0000000000..077f541a13 --- /dev/null +++ b/lib/layers/convolutional/ZeroPadding2D.js @@ -0,0 +1,146 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class ZeroPadding2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'ZeroPadding2D'; + const { + padding = [[1, 1], [1, 1]], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(padding)) { + if (Array.isArray(padding[0])) { + this.padding = padding; + } else { + this.padding = [[padding[0], padding[0]], [padding[1], padding[1]]]; + } + } else { + this.padding = [[padding, padding], [padding, padding]]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] + this.padding[0][0] + this.padding[0][1], this.inputShape[1] + this.padding[1][0] + this.padding[1][1], this.inputShape[2]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor.hi(this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2]).lo(this.padding[0][0], this.padding[1][0], 0), x.tensor); + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(2, 0, 1); + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = this.dataFormat === 'channels_first' ? [0, this.padding[0][0], this.padding[1][0]] : [this.padding[0][0], this.padding[1][0], 0]; + const sliceEnd = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0], this.inputShape[2] + this.padding[1][0]] : [this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2]]; + + _ndarrayOps.default.assigns(this.indexMap.tensor, -1); + + _ndarrayOps.default.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor); + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0] + this.padding[0][1], this.inputShape[2] + this.padding[1][0] + this.padding[1][1]] : [this.inputShape[0] + this.padding[0][0] + this.padding[0][1], this.inputShape[1] + this.padding[1][0] + this.padding[1][1], this.inputShape[2]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = ZeroPadding2D; \ No newline at end of file diff --git a/lib/layers/convolutional/ZeroPadding3D.js b/lib/layers/convolutional/ZeroPadding3D.js new file mode 100644 index 0000000000..69917c9e9b --- /dev/null +++ b/lib/layers/convolutional/ZeroPadding3D.js @@ -0,0 +1,146 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class ZeroPadding3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'ZeroPadding3D'; + const { + padding = [[1, 1], [1, 1], [1, 1]], + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(padding)) { + if (Array.isArray(padding[0])) { + this.padding = padding; + } else { + this.padding = [[padding[0], padding[0]], [padding[1], padding[1]], [padding[2], padding[2]]]; + } + } else { + this.padding = [[padding, padding], [padding, padding], [padding, padding]]; + } + + this.dataFormat = data_format; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + this.outputShape = [this.inputShape[0] + this.padding[0][0] + this.padding[0][1], this.inputShape[1] + this.padding[1][0] + this.padding[1][1], this.inputShape[2] + this.padding[2][0] + this.padding[2][1], this.inputShape[3]]; + this.output = new _Tensor.default([], this.outputShape); + + _ndarrayOps.default.assign(this.output.tensor.hi(this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2] + this.padding[2][0], this.inputShape[3]).lo(this.padding[0][0], this.padding[1][0], this.padding[2][0], 0), x.tensor); + + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(3, 0, 1, 2); + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMap = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + const sliceStart = this.dataFormat === 'channels_first' ? [0, this.padding[0][0], this.padding[1][0], this.padding[2][0]] : [this.padding[0][0], this.padding[1][0], this.padding[2][0], 0]; + const sliceEnd = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0], this.inputShape[2] + this.padding[1][0], this.inputShape[3] + this.padding[2][0]] : [this.inputShape[0] + this.padding[0][0], this.inputShape[1] + this.padding[1][0], this.inputShape[2] + this.padding[2][0], this.inputShape[3]]; + + _ndarrayOps.default.assigns(this.indexMap.tensor, -1); + + _ndarrayOps.default.assign(this.indexMap.tensor.hi(...sliceEnd).lo(...sliceStart), indices.tensor); + + this.indexMap.reshapeTo2DSquare(); + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.originalShape; + this.outputShape = this.dataFormat === 'channels_first' ? [this.inputShape[0], this.inputShape[1] + this.padding[0][0] + this.padding[0][1], this.inputShape[2] + this.padding[1][0] + this.padding[1][1], this.inputShape[3] + this.padding[2][0] + this.padding[2][1]] : [this.inputShape[0] + this.padding[0][0] + this.padding[0][1], this.inputShape[1] + this.padding[1][0] + this.padding[1][1], this.inputShape[2] + this.padding[2][0] + this.padding[2][1], this.inputShape[3]]; + + this._createIndexMap(x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2DSquare(); + } + } + +} + +exports.default = ZeroPadding3D; \ No newline at end of file diff --git a/lib/layers/convolutional/index.js b/lib/layers/convolutional/index.js new file mode 100644 index 0000000000..ddb1105c55 --- /dev/null +++ b/lib/layers/convolutional/index.js @@ -0,0 +1,119 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Conv1D", { + enumerable: true, + get: function () { + return _Conv1D.default; + } +}); +Object.defineProperty(exports, "Conv2D", { + enumerable: true, + get: function () { + return _Conv2D.default; + } +}); +Object.defineProperty(exports, "SeparableConv2D", { + enumerable: true, + get: function () { + return _SeparableConv2D.default; + } +}); +Object.defineProperty(exports, "Conv2DTranspose", { + enumerable: true, + get: function () { + return _Conv2DTranspose.default; + } +}); +Object.defineProperty(exports, "Conv3D", { + enumerable: true, + get: function () { + return _Conv3D.default; + } +}); +Object.defineProperty(exports, "Cropping1D", { + enumerable: true, + get: function () { + return _Cropping1D.default; + } +}); +Object.defineProperty(exports, "Cropping2D", { + enumerable: true, + get: function () { + return _Cropping2D.default; + } +}); +Object.defineProperty(exports, "Cropping3D", { + enumerable: true, + get: function () { + return _Cropping3D.default; + } +}); +Object.defineProperty(exports, "UpSampling1D", { + enumerable: true, + get: function () { + return _UpSampling1D.default; + } +}); +Object.defineProperty(exports, "UpSampling2D", { + enumerable: true, + get: function () { + return _UpSampling2D.default; + } +}); +Object.defineProperty(exports, "UpSampling3D", { + enumerable: true, + get: function () { + return _UpSampling3D.default; + } +}); +Object.defineProperty(exports, "ZeroPadding1D", { + enumerable: true, + get: function () { + return _ZeroPadding1D.default; + } +}); +Object.defineProperty(exports, "ZeroPadding2D", { + enumerable: true, + get: function () { + return _ZeroPadding2D.default; + } +}); +Object.defineProperty(exports, "ZeroPadding3D", { + enumerable: true, + get: function () { + return _ZeroPadding3D.default; + } +}); + +var _Conv1D = _interopRequireDefault(require("./Conv1D")); + +var _Conv2D = _interopRequireDefault(require("./Conv2D")); + +var _SeparableConv2D = _interopRequireDefault(require("./SeparableConv2D")); + +var _Conv2DTranspose = _interopRequireDefault(require("./Conv2DTranspose")); + +var _Conv3D = _interopRequireDefault(require("./Conv3D")); + +var _Cropping1D = _interopRequireDefault(require("./Cropping1D")); + +var _Cropping2D = _interopRequireDefault(require("./Cropping2D")); + +var _Cropping3D = _interopRequireDefault(require("./Cropping3D")); + +var _UpSampling1D = _interopRequireDefault(require("./UpSampling1D")); + +var _UpSampling2D = _interopRequireDefault(require("./UpSampling2D")); + +var _UpSampling3D = _interopRequireDefault(require("./UpSampling3D")); + +var _ZeroPadding1D = _interopRequireDefault(require("./ZeroPadding1D")); + +var _ZeroPadding2D = _interopRequireDefault(require("./ZeroPadding2D")); + +var _ZeroPadding3D = _interopRequireDefault(require("./ZeroPadding3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/core/Activation.js b/lib/layers/core/Activation.js new file mode 100644 index 0000000000..ff8c191de5 --- /dev/null +++ b/lib/layers/core/Activation.js @@ -0,0 +1,111 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var activations = _interopRequireWildcard(require("../../activations")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Activation extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Activation'; + const { + activation = 'linear' + } = attrs; + this.activation = activation; + this.activationFunc = activations[activation]; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + call(x) { + if (this.activation === 'linear') { + this.output = x; + return this.output; + } + + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = new _Tensor.default(new x.arrayType(x.tensor.data), x.tensor.shape); + this.activationFunc(this.output); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = Activation; \ No newline at end of file diff --git a/lib/layers/core/Dense.js b/lib/layers/core/Dense.js new file mode 100644 index 0000000000..b1bd4b3f1b --- /dev/null +++ b/lib/layers/core/Dense.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var activations = _interopRequireWildcard(require("../../activations")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class Dense extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Dense'; + const { + units = 1, + activation = 'linear', + input_dim = null, + use_bias = true + } = attrs; + this.activation = activation; + this.activationFunc = activations[this.activation]; + this.units = units; + this.input_dim = input_dim; + this.use_bias = use_bias; + this.params = this.use_bias ? ['kernel', 'bias'] : ['kernel']; + + if (this.input_dim) { + this.inputShape = [this.input_dim]; + } + + if (this.gpu) { + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = new _Tensor.default([], [this.units]); + + if (this.use_bias) { + _ndarrayOps.default.assign(this.output.tensor, this.weights['bias'].tensor); + } + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['kernel'].tensor.transpose(1, 0), x.tensor, 1, this.output.tensor); + this.activationFunc(this.output); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new _Tensor.default([], [this.units]); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [this.units]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const matMulInputs = [{ + input: x, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }]; + + if (this.use_bias) { + matMulInputs.push({ + input: this.weights['bias'], + name: 'C' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ + value: this.use_bias ? 1 : 0, + type: 'bool', + name: 'addC' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }] + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Dense; \ No newline at end of file diff --git a/lib/layers/core/Dropout.js b/lib/layers/core/Dropout.js new file mode 100644 index 0000000000..60e9b0c37d --- /dev/null +++ b/lib/layers/core/Dropout.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Dropout extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Dropout'; + const { + rate = 0.5 + } = attrs; + this.rate = Math.min(Math.max(0, rate), 1); + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = Dropout; \ No newline at end of file diff --git a/lib/layers/core/Flatten.js b/lib/layers/core/Flatten.js new file mode 100644 index 0000000000..df0e85f85b --- /dev/null +++ b/lib/layers/core/Flatten.js @@ -0,0 +1,128 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const flattenProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int outputSize;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(outputSize) * outTex.x);\r\n int out_y = 0;\r\n\r\n int i = int(floor(float(out_x) / float(inputCols)));\r\n int j = int(mod(float(out_x), float(inputCols)));\r\n outColor = vec4(texelFetch(x, ivec2(j, i), 0).r);\r\n}\r\n"; +const flattenFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int outputSize;\r\nuniform int inputRows;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(outputSize) * outTex.x);\r\n int out_y = 0;\r\n\r\n int rowIndex = int(mod(floor(float(out_x) / float(inputCols)), float(inputRows)));\r\n int colIndex = int(mod(float(out_x), float(inputCols)));\r\n int fragmentIndex = int(floor(float(out_x) / (float(inputRows) * float(inputCols))));\r\n colIndex += fragmentIndex * inputCols;\r\n outColor = vec4(texelFetch(x, ivec2(colIndex, rowIndex), 0).r);\r\n}\r\n"; + +class Flatten extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Flatten'; + + if (this.gpu) { + this.flattenProgram = _WebGL.webgl2.compileProgram(flattenProgramSource); + this.flattenFragmentsProgram = _WebGL.webgl2.compileProgram(flattenFragmentsProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (x.tensor.shape.length <= 1) { + this.output = x; + } else { + this.output = new _Tensor.default([], [x.tensor.shape.reduce((a, b) => a * b, 1)]); + this.output.replaceTensorData(x.tensor.data); + } + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + + if (!this.output) { + this.output = new _Tensor.default([], [x.glTextureShape.reduce((a, b) => a * b, 1)]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (x.glTextureFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + + _WebGL.webgl2.runProgram({ + program: this.flattenFragmentsProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'outputSize' + }, { + value: x.glTextureShape[0], + type: 'int', + name: 'inputRows' + }, { + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }], + supportsTextureFragments: true + }); + + x.removeGLTextureFragmentsAsColStack(); + } else { + _WebGL.webgl2.runProgram({ + program: this.flattenProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'outputSize' + }, { + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Flatten; \ No newline at end of file diff --git a/lib/layers/core/Permute.js b/lib/layers/core/Permute.js new file mode 100644 index 0000000000..cafda5e68a --- /dev/null +++ b/lib/layers/core/Permute.js @@ -0,0 +1,194 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _last2 = _interopRequireDefault(require("lodash/last")); + +var _range2 = _interopRequireDefault(require("lodash/range")); + +var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Permute extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Permute'; + const { + dims = [] + } = attrs; + this.dims = dims.map(dim => dim - 1); + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (x.tensor.shape.length <= 1 || (0, _isEqual2.default)((0, _range2.default)(x.tensor.shape.length), this.dims)) { + this.output = x; + return this.output; + } + + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dims.length !== x.tensor.shape.length) { + this.throwError('The specified dims permutation must match the number of dimensions.'); + } + + const outputShape = this.dims.map(i => x.tensor.shape[i]); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.assign(this.output.tensor, x.tensor.transpose(...this.dims)); + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + if (this.inputShape.length === 2) { + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + } else if (this.inputShape.length === 3) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, j, null), i * this.inputShape[1] + j); + } + } + } else if (this.inputShape.length === 4) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + for (let k = 0; k < this.inputShape[2]; k++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, j, k, null), i * this.inputShape[1] * this.inputShape[2] + j * this.inputShape[2] + k); + } + } + } + } + + for (let c = 0; c < (0, _last2.default)(this.inputShape); c++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(...Array(this.inputShape.length - 1).fill(null), c), c); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, (0, _last2.default)(this.inputShape)); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + const outputShape = this.dims.map(i => this.inputShape[i]); + this.indexMap = new _Tensor.default([], outputShape, { + type: Int32Array + }); + + _ndarrayOps.default.assign(this.indexMap.tensor, indices.tensor.transpose(...this.dims)); + + if (outputShape.length > 2) { + this.indexMap.reshapeTo2D(); + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + this.inputShape = x.tensor.shape; + + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + + this._createIndexMap(); + + if (!this.output) { + const outputShape = this.dims.map(i => this.inputShape[i]); + this.output = new _Tensor.default([], outputShape); + + if (outputShape.length > 2) { + this.output.reshapeTo2D(); + } + + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = Permute; \ No newline at end of file diff --git a/lib/layers/core/RepeatVector.js b/lib/layers/core/RepeatVector.js new file mode 100644 index 0000000000..df1eab5a16 --- /dev/null +++ b/lib/layers/core/RepeatVector.js @@ -0,0 +1,87 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayUnsqueeze = _interopRequireDefault(require("ndarray-unsqueeze")); + +var _ndarrayTile = _interopRequireDefault(require("ndarray-tile")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = texture(x, vec2(outTex.x, 0));\r\n}\r\n"; + +class RepeatVector extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'RepeatVector'; + const { + n = 1 + } = attrs; + this.n = n; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (x.tensor.shape.length !== 1) { + this.throwError('Only 1D tensor inputs allowed.'); + } + + this.output = new _Tensor.default([], [this.n, x.tensor.shape[1]]); + this.output.tensor = (0, _ndarrayTile.default)((0, _ndarrayUnsqueeze.default)(x.tensor, 0), [this.n, 1]); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [this.n, x.glTextureShape[1]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = RepeatVector; \ No newline at end of file diff --git a/lib/layers/core/Reshape.js b/lib/layers/core/Reshape.js new file mode 100644 index 0000000000..c056f7050d --- /dev/null +++ b/lib/layers/core/Reshape.js @@ -0,0 +1,180 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _last2 = _interopRequireDefault(require("lodash/last")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; + +class Reshape extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Reshape'; + const { + target_shape = [] + } = attrs; + this.targetShape = target_shape; + + if (this.gpu) { + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.targetShape.reduce((a, b) => a * b, 1) !== x.tensor.size) { + this.throwError('The total size of new array must be unchanged in reshape layer.'); + } + + this.output = new _Tensor.default([], this.targetShape); + this.output.replaceTensorData(x.tensor.data); + } + + _createIndexMap() { + if (this.indexMap) { + return; + } + + const indices = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesRow = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + const indicesCol = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + if (this.inputShape.length === 2) { + for (let i = 0; i < this.inputShape[0]; i++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, null), i); + } + } else if (this.inputShape.length === 3) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, j, null), i * this.inputShape[1] + j); + } + } + } else if (this.inputShape.length === 4) { + for (let i = 0; i < this.inputShape[0]; i++) { + for (let j = 0; j < this.inputShape[1]; j++) { + for (let k = 0; k < this.inputShape[2]; k++) { + _ndarrayOps.default.assigns(indicesRow.tensor.pick(i, j, k, null), i * this.inputShape[1] * this.inputShape[2] + j * this.inputShape[2] + k); + } + } + } + } + + for (let c = 0; c < (0, _last2.default)(this.inputShape); c++) { + _ndarrayOps.default.assigns(indicesCol.tensor.pick(...Array(this.inputShape.length - 1).fill(null), c), c); + } + + _ndarrayOps.default.muls(indices.tensor, indicesRow.tensor, (0, _last2.default)(this.inputShape)); + + _ndarrayOps.default.addeq(indices.tensor, indicesCol.tensor); + + this.indexMap = new _Tensor.default([], this.targetShape, { + type: Int32Array + }); + this.indexMap.replaceTensorData(new Int32Array(indices.tensor.data)); + + if (this.targetShape.length > 2) { + this.indexMap.reshapeTo2D(); + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int' + }); + } + + _callGPU(x) { + if (!x.glTexture) { + this.inputShape = x.tensor.shape; + + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.targetShape); + + if (this.targetShape.length > 2) { + this.output.reshapeTo2D(); + } + + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = Reshape; \ No newline at end of file diff --git a/lib/layers/core/SpatialDropout1D.js b/lib/layers/core/SpatialDropout1D.js new file mode 100644 index 0000000000..a42b324b4b --- /dev/null +++ b/lib/layers/core/SpatialDropout1D.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class SpatialDropout1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'SpatialDropout1D'; + const { + p = 0.5 + } = attrs; + this.p = Math.min(Math.max(0, p), 1); + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = SpatialDropout1D; \ No newline at end of file diff --git a/lib/layers/core/SpatialDropout2D.js b/lib/layers/core/SpatialDropout2D.js new file mode 100644 index 0000000000..38949bd9f7 --- /dev/null +++ b/lib/layers/core/SpatialDropout2D.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class SpatialDropout2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'SpatialDropout2D'; + const { + rate = 0.5, + data_format = 'channels_last' + } = attrs; + this.rate = Math.min(Math.max(0, rate), 1); + this.dataFormat = data_format; + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = SpatialDropout2D; \ No newline at end of file diff --git a/lib/layers/core/SpatialDropout3D.js b/lib/layers/core/SpatialDropout3D.js new file mode 100644 index 0000000000..abbe65a7ff --- /dev/null +++ b/lib/layers/core/SpatialDropout3D.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class SpatialDropout3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'SpatialDropout3D'; + const { + rate = 0.5, + data_format = 'channels_last' + } = attrs; + this.rate = Math.min(Math.max(0, rate), 1); + this.dataFormat = data_format; + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = SpatialDropout3D; \ No newline at end of file diff --git a/lib/layers/core/index.js b/lib/layers/core/index.js new file mode 100644 index 0000000000..9a078e0b87 --- /dev/null +++ b/lib/layers/core/index.js @@ -0,0 +1,87 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Dense", { + enumerable: true, + get: function () { + return _Dense.default; + } +}); +Object.defineProperty(exports, "Activation", { + enumerable: true, + get: function () { + return _Activation.default; + } +}); +Object.defineProperty(exports, "Dropout", { + enumerable: true, + get: function () { + return _Dropout.default; + } +}); +Object.defineProperty(exports, "SpatialDropout1D", { + enumerable: true, + get: function () { + return _SpatialDropout1D.default; + } +}); +Object.defineProperty(exports, "SpatialDropout2D", { + enumerable: true, + get: function () { + return _SpatialDropout2D.default; + } +}); +Object.defineProperty(exports, "SpatialDropout3D", { + enumerable: true, + get: function () { + return _SpatialDropout3D.default; + } +}); +Object.defineProperty(exports, "Flatten", { + enumerable: true, + get: function () { + return _Flatten.default; + } +}); +Object.defineProperty(exports, "Reshape", { + enumerable: true, + get: function () { + return _Reshape.default; + } +}); +Object.defineProperty(exports, "Permute", { + enumerable: true, + get: function () { + return _Permute.default; + } +}); +Object.defineProperty(exports, "RepeatVector", { + enumerable: true, + get: function () { + return _RepeatVector.default; + } +}); + +var _Dense = _interopRequireDefault(require("./Dense")); + +var _Activation = _interopRequireDefault(require("./Activation")); + +var _Dropout = _interopRequireDefault(require("./Dropout")); + +var _SpatialDropout1D = _interopRequireDefault(require("./SpatialDropout1D")); + +var _SpatialDropout2D = _interopRequireDefault(require("./SpatialDropout2D")); + +var _SpatialDropout3D = _interopRequireDefault(require("./SpatialDropout3D")); + +var _Flatten = _interopRequireDefault(require("./Flatten")); + +var _Reshape = _interopRequireDefault(require("./Reshape")); + +var _Permute = _interopRequireDefault(require("./Permute")); + +var _RepeatVector = _interopRequireDefault(require("./RepeatVector")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/embeddings/Embedding.js b/lib/layers/embeddings/Embedding.js new file mode 100644 index 0000000000..0011414a94 --- /dev/null +++ b/lib/layers/embeddings/Embedding.js @@ -0,0 +1,94 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D embeddings;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 x_size = textureSize(x, 0);\r\n ivec2 embeddings_size = textureSize(embeddings, 0);\r\n int out_x = int(float(embeddings_size[0]) * outTex.x);\r\n int out_y = int(float(x_size[0]) * outTex.y);\r\n\r\n int index = int(texelFetch(x, ivec2(out_y, 0), 0).r);\r\n outColor = texelFetch(embeddings, ivec2(out_x, index), 0);\r\n}\r\n"; + +class Embedding extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Embedding'; + const { + input_dim = 1, + output_dim = 1, + input_length = 0, + mask_zero = false + } = attrs; + this.inputDim = input_dim; + this.outputDim = output_dim; + this.inputLength = input_length; + this.maskZero = mask_zero; + this.params = ['embeddings']; + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.output = new _Tensor.default([], [x.tensor.shape[0], this.weights['embeddings'].tensor.shape[1]]); + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + _ndarrayOps.default.assign(this.output.tensor.pick(i, null), this.weights['embeddings'].tensor.pick(x.tensor.get(i), null)); + } + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [x.glTextureShape[1], this.weights['embeddings'].glTextureShape[1]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.weights['embeddings'], + name: 'embeddings' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Embedding; \ No newline at end of file diff --git a/lib/layers/embeddings/index.js b/lib/layers/embeddings/index.js new file mode 100644 index 0000000000..68fc079719 --- /dev/null +++ b/lib/layers/embeddings/index.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Embedding", { + enumerable: true, + get: function () { + return _Embedding.default; + } +}); + +var _Embedding = _interopRequireDefault(require("./Embedding")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/index.js b/lib/layers/index.js new file mode 100644 index 0000000000..218f1c290e --- /dev/null +++ b/lib/layers/index.js @@ -0,0 +1,148 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var _exportNames = { + InputLayer: true +}; +Object.defineProperty(exports, "InputLayer", { + enumerable: true, + get: function () { + return _InputLayer.default; + } +}); + +var _InputLayer = _interopRequireDefault(require("./InputLayer")); + +var _advanced_activations = require("./advanced_activations"); + +Object.keys(_advanced_activations).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _advanced_activations[key]; + } + }); +}); + +var _convolutional = require("./convolutional"); + +Object.keys(_convolutional).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _convolutional[key]; + } + }); +}); + +var _core = require("./core"); + +Object.keys(_core).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _core[key]; + } + }); +}); + +var _embeddings = require("./embeddings"); + +Object.keys(_embeddings).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _embeddings[key]; + } + }); +}); + +var _merge = require("./merge"); + +Object.keys(_merge).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _merge[key]; + } + }); +}); + +var _noise = require("./noise"); + +Object.keys(_noise).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _noise[key]; + } + }); +}); + +var _normalization = require("./normalization"); + +Object.keys(_normalization).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _normalization[key]; + } + }); +}); + +var _pooling = require("./pooling"); + +Object.keys(_pooling).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _pooling[key]; + } + }); +}); + +var _recurrent = require("./recurrent"); + +Object.keys(_recurrent).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _recurrent[key]; + } + }); +}); + +var _wrappers = require("./wrappers"); + +Object.keys(_wrappers).forEach(function (key) { + if (key === "default" || key === "__esModule") return; + if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; + Object.defineProperty(exports, key, { + enumerable: true, + get: function () { + return _wrappers[key]; + } + }); +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/merge/Add.js b/lib/layers/merge/Add.js new file mode 100644 index 0000000000..1cbd95c0c4 --- /dev/null +++ b/lib/layers/merge/Add.js @@ -0,0 +1,48 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Add extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Add'; + this.mode = 'sum'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + for (let i = 0; i < inputs.length; i++) { + _ndarrayOps.default.addeq(this.output.tensor, inputs[i].tensor); + } + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('add', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Add; \ No newline at end of file diff --git a/lib/layers/merge/Average.js b/lib/layers/merge/Average.js new file mode 100644 index 0000000000..7386a75bdb --- /dev/null +++ b/lib/layers/merge/Average.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Average extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Average'; + this.mode = 'ave'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + for (let i = 0; i < inputs.length; i++) { + _ndarrayOps.default.addeq(this.output.tensor, inputs[i].tensor); + } + + _ndarrayOps.default.divseq(this.output.tensor, inputs.length); + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('average', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Average; \ No newline at end of file diff --git a/lib/layers/merge/Concatenate.js b/lib/layers/merge/Concatenate.js new file mode 100644 index 0000000000..1ae70447b6 --- /dev/null +++ b/lib/layers/merge/Concatenate.js @@ -0,0 +1,143 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _sum2 = _interopRequireDefault(require("lodash/sum")); + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayConcatRows = _interopRequireDefault(require("ndarray-concat-rows")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Concatenate extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Concatenate'; + this.mode = 'concat'; + const { + axis = -1 + } = attrs; + this.concatAxis = axis <= 0 ? axis : axis - 1; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + + const _concatAxis = this.concatAxis < 0 ? outputShape.length + this.concatAxis : this.concatAxis; + + inputs.slice(1, inputs.length).forEach(x => { + const d = x.tensor.shape.slice()[_concatAxis]; + + outputShape[_concatAxis] += d; + }); + this.output = new _Tensor.default([], outputShape); + + if (_concatAxis === 0) { + (0, _ndarrayConcatRows.default)(this.output.tensor, inputs.map(x => x.tensor)); + } else { + let dimsAxisSwap = [_concatAxis]; + + for (let i = 0; i < inputs[0].tensor.shape.length; i++) { + if (i !== _concatAxis) dimsAxisSwap.push(i); + } + + (0, _ndarrayConcatRows.default)(this.output.tensor.transpose(...dimsAxisSwap), inputs.map(x => x.tensor.transpose(...dimsAxisSwap))); + } + } + + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + }); + const outputShape = inputs[0].glTextureShape.slice(); + let _concatAxis = 1; + + if (inputs[0].is2DReshaped) { + if (this.concatAxis === -1 || this.concatAxis === inputs[0].originalShape.length - 1) { + _concatAxis = 1; + } else { + this.throwError('specified axis not supported for now.'); + } + } else { + if (this.concatAxis === -1 || this.concatAxis === 1) { + _concatAxis = 1; + } else if (this.concatAxis === -2 || this.concatAxis === 0) { + _concatAxis = 0; + } else { + this.throwError('specified axis not supported for now.'); + } + } + + outputShape[_concatAxis] = (0, _sum2.default)(inputs.map(input => input.glTextureShape[_concatAxis])); + + if (!this.output) { + this.output = new _Tensor.default([], outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: _concatAxis === 1 + }); + + if (inputs[0].is1D) { + this.output.is1D = inputs[0].is1D; + } else if (inputs[0].is2DReshaped) { + this.output.is2DReshaped = inputs[0].is2DReshaped; + this.output.originalShape = inputs[0].originalShape.slice(); + + const _concatAxis = this.concatAxis < 0 ? this.output.originalShape.length + this.concatAxis : this.concatAxis; + + this.output.originalShape[_concatAxis] = (0, _sum2.default)(inputs.map(input => input.originalShape[_concatAxis])); + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.output.originalShape, false, _concatAxis); + } + } + + if (!this.mergeProgram) { + const outputShape = this.output.glTextureFragments ? this.output.glTextureFragmentShape : this.output.glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('concatenate', inputs.length, inputs.map(input => input.glTextureShape), outputShape, _concatAxis); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + _WebGL.webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: inputs.map((input, i) => ({ + input, + name: `inputs[${i}]` + })), + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = Concatenate; \ No newline at end of file diff --git a/lib/layers/merge/Dot.js b/lib/layers/merge/Dot.js new file mode 100644 index 0000000000..b0c09931b9 --- /dev/null +++ b/lib/layers/merge/Dot.js @@ -0,0 +1,159 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const mergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D input1;\r\nuniform sampler2D input2;\r\nuniform int rows;\r\nuniform int cols;\r\nuniform int dotAxis1;\r\nuniform int dotAxis2;\r\nuniform int commonDim;\r\nuniform bool normalize;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(cols) * outTex.x);\r\n int out_y = int(float(rows) * outTex.y);\r\n\r\n float sum = 0.;\r\n float a = 0.;\r\n float b = 0.;\r\n float norm1 = 0.;\r\n float norm2 = 0.;\r\n\r\n for (int i = 0; i < commonDim; ++i) {\r\n if (dotAxis1 == 0 && dotAxis2 == 0) {\r\n a = texelFetch(input1, ivec2(out_y, i), 0).r;\r\n b = texelFetch(input2, ivec2(out_x, i), 0).r;\r\n } else if (dotAxis1 == 1 && dotAxis2 == 1) {\r\n a = texelFetch(input1, ivec2(i, out_y), 0).r;\r\n b = texelFetch(input2, ivec2(i, out_x), 0).r;\r\n }\r\n\r\n sum += a * b;\r\n\r\n if (normalize) {\r\n norm1 += a * a;\r\n norm2 += b * b;\r\n }\r\n }\r\n\r\n if (normalize) {\r\n sum /= sqrt(norm1) * sqrt(norm2);\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class Dot extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Dot'; + this.mode = 'dot'; + const { + axes = -1, + normalize = false + } = attrs; + + if (Array.isArray(axes)) { + this.dotAxes = [axes[0] <= 0 ? axes[0] : axes[0] - 1, axes[1] <= 0 ? axes[1] : axes[1] - 1]; + } else { + this.dotAxes = [axes <= 0 ? axes : axes - 1, axes <= 0 ? axes : axes - 1]; + } + + this.normalize = normalize; + + if (this.gpu) { + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + } + + _calcOutputShape(inputShapes) { + let shape1 = inputShapes[0].slice(); + let shape2 = inputShapes[1].slice(); + shape1.splice(this.dotAxes[0], 1); + shape2.splice(this.dotAxes[1], 1); + this.outputShape = shape1.concat(shape2); + + if (this.outputShape.length === 1) { + this.outputShape.push(1); + } + } + + _callCPU(inputs) { + this._calcOutputShape([inputs[0].tensor.shape, inputs[1].tensor.shape]); + + this.output = new _Tensor.default([], this.outputShape); + + if (inputs[0].tensor.shape.length === 2 && inputs[1].tensor.shape.length === 2) { + if (this.dotAxes[0] === 0 && this.dotAxes[1] === 0) { + if (this.normalize) { + for (let i = 0; i < inputs[0].tensor.shape[1]; i++) { + _ndarrayOps.default.divseq(inputs[0].tensor.pick(null, i), _ndarrayOps.default.norm2(inputs[0].tensor.pick(null, i))); + } + + for (let i = 0; i < inputs[1].tensor.shape[1]; i++) { + _ndarrayOps.default.divseq(inputs[1].tensor.pick(null, i), _ndarrayOps.default.norm2(inputs[1].tensor.pick(null, i))); + } + } + + (0, _ndarrayGemm.default)(this.output.tensor, inputs[0].tensor.transpose(1, 0), inputs[1].tensor); + } else if (this.dotAxes[0] === 1 && this.dotAxes[1] === 1) { + if (this.normalize) { + for (let i = 0; i < inputs[0].tensor.shape[0]; i++) { + _ndarrayOps.default.divseq(inputs[0].tensor.pick(i, null), _ndarrayOps.default.norm2(inputs[0].tensor.pick(i, null))); + } + + for (let i = 0; i < inputs[1].tensor.shape[0]; i++) { + _ndarrayOps.default.divseq(inputs[1].tensor.pick(i, null), _ndarrayOps.default.norm2(inputs[1].tensor.pick(i, null))); + } + } + + (0, _ndarrayGemm.default)(this.output.tensor, inputs[0].tensor, inputs[1].tensor.transpose(1, 0)); + } + } else { + this.throwError('dot mode for 3+ dim tensors not yet implemented.'); + } + } + + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ + type: '2d', + format: 'float' + }); + } + }); + + this._calcOutputShape([inputs[0].glTextureShape, inputs[1].glTextureShape]); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const commonDim = inputs[0].glTextureShape[this.dotAxes[0]]; + + _WebGL.webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: [{ + input: inputs[0], + name: 'input1' + }, { + input: inputs[1], + name: 'input2' + }], + uniforms: [{ + value: this.output.glTextureShape[0], + type: 'int', + name: 'rows' + }, { + value: this.output.glTextureShape[1], + type: 'int', + name: 'cols' + }, { + value: this.dotAxes[0], + type: 'int', + name: 'dotAxis1' + }, { + value: this.dotAxes[1], + type: 'int', + name: 'dotAxis2' + }, { + value: commonDim, + type: 'int', + name: 'commonDim' + }, { + value: +this.normalize, + type: 'bool', + name: 'normalize' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Dot; \ No newline at end of file diff --git a/lib/layers/merge/Maximum.js b/lib/layers/merge/Maximum.js new file mode 100644 index 0000000000..a80055bd19 --- /dev/null +++ b/lib/layers/merge/Maximum.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Maximum extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Maximum'; + this.mode = 'max'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.assign(this.output.tensor, inputs[0].tensor); + + for (let i = 1; i < inputs.length; i++) { + _ndarrayOps.default.maxeq(this.output.tensor, inputs[i].tensor); + } + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('maximum', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Maximum; \ No newline at end of file diff --git a/lib/layers/merge/Minimum.js b/lib/layers/merge/Minimum.js new file mode 100644 index 0000000000..f935cc4db5 --- /dev/null +++ b/lib/layers/merge/Minimum.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Minimum extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Minimum'; + this.mode = 'min'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.assign(this.output.tensor, inputs[0].tensor); + + for (let i = 1; i < inputs.length; i++) { + _ndarrayOps.default.mineq(this.output.tensor, inputs[i].tensor); + } + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('minimum', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Minimum; \ No newline at end of file diff --git a/lib/layers/merge/Multiply.js b/lib/layers/merge/Multiply.js new file mode 100644 index 0000000000..bf2a9833fe --- /dev/null +++ b/lib/layers/merge/Multiply.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Multiply extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Multiply'; + this.mode = 'mul'; + } + + _callCPU(inputs) { + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.assigns(this.output.tensor, 1); + + for (let i = 0; i < inputs.length; i++) { + _ndarrayOps.default.muleq(this.output.tensor, inputs[i].tensor); + } + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('multiply', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Multiply; \ No newline at end of file diff --git a/lib/layers/merge/Subtract.js b/lib/layers/merge/Subtract.js new file mode 100644 index 0000000000..23fe170588 --- /dev/null +++ b/lib/layers/merge/Subtract.js @@ -0,0 +1,50 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Merge2 = _interopRequireDefault(require("./_Merge")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _createGLSLProgram = _interopRequireDefault(require("../../webgl/dynamic/createGLSLProgram")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class Subtract extends _Merge2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Subtract'; + this.mode = 'diff'; + } + + _callCPU(inputs) { + if (inputs.length !== 2) { + this.throwError('Inputs should be an array of 2 Tensors.'); + } + + const outputShape = inputs[0].tensor.shape.slice(); + this.output = new _Tensor.default([], outputShape); + + _ndarrayOps.default.sub(this.output.tensor, inputs[0].tensor, inputs[1].tensor); + } + + _callGPU(inputs) { + if (!this.mergeProgram) { + const shape = inputs[0].glTextureFragments ? inputs[0].glTextureFragmentShape : inputs[0].glTextureShape; + const mergeProgramSource = (0, _createGLSLProgram.default)('subtract', inputs.length, shape); + this.mergeProgram = _WebGL.webgl2.compileProgram(mergeProgramSource); + } + + super._callGPU(inputs); + } + +} + +exports.default = Subtract; \ No newline at end of file diff --git a/lib/layers/merge/_Merge.js b/lib/layers/merge/_Merge.js new file mode 100644 index 0000000000..79543bc51b --- /dev/null +++ b/lib/layers/merge/_Merge.js @@ -0,0 +1,144 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class _Merge extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_Merge'; + this.isMergeLayer = true; + } + + call(inputs) { + if (this.gpu) { + this._callGPU(inputs); + } else { + const valid = this._validateInputs(inputs); + + if (!valid) { + this.throwError('Invalid inputs to call method.'); + } + + this._callCPU(inputs); + } + + return this.output; + } + + _validateInputs(inputs) { + const shapes = inputs.map(x => x.tensor.shape.slice()); + + if (['sum', 'diff', 'mul', 'ave', 'max', 'min'].indexOf(this.mode) > -1) { + if (!shapes.every(shape => (0, _isEqual2.default)(shape, shapes[0]))) { + this.throwError(`All input shapes must be the same for mode ${this.mode}.`); + } + } + + if (this.mode === 'dot') { + if (inputs.length !== 2) { + this.throwError(`Exactly 2 inputs required for mode ${this.mode}.`); + } + + if (this.dotAxes[0] < 0) { + this.dotAxes[0] = shapes[0].length + this.dotAxes[0]; + } + + if (this.dotAxes[1] < 0) { + this.dotAxes[1] = shapes[1].length + this.dotAxes[1]; + } + + if (shapes[0][this.dotAxes[0]] !== shapes[1][this.dotAxes[1]]) { + this.throwError('Dimensions incompatibility using dot mode.'); + } + } else if (this.mode === 'concat') { + let nonConcatShapes = shapes.slice(); + + let _concatAxis = this.concatAxis < 0 ? nonConcatShapes[0].length + this.concatAxis : this.concatAxis; + + if (this.concatAxis === 0) _concatAxis = 0; + (0, _range2.default)(nonConcatShapes.length).forEach(i => { + nonConcatShapes[i].splice(_concatAxis, 1); + }); + + if (!nonConcatShapes.every(shape => (0, _isEqual2.default)(shape, nonConcatShapes[0]))) { + this.throwError('In concat mode, all shapes must be the same except along the concat axis.'); + } + } + + return true; + } + + _callCPU() {} + + _callGPU(inputs) { + inputs.forEach(input => { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + }); + + if (!this.output) { + this.output = new _Tensor.default([], inputs[0].glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (inputs[0].is1D) { + this.output.is1D = inputs[0].is1D; + } else if (inputs[0].is2DReshaped || inputs[0].is2DSquareReshaped) { + if (inputs[0].is2DReshaped) { + this.output.is2DReshaped = inputs[0].is2DReshaped; + } else if (inputs[0].is2DSquareReshaped) { + this.output.is2DSquareReshaped = inputs[0].is2DSquareReshaped; + } + + this.output.originalShape = inputs[0].originalShape.slice(); + this.output.indicesForReshaped = inputs[0].indicesForReshaped; + } + } + + _WebGL.webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: inputs.map((input, i) => ({ + input, + name: `inputs[${i}]` + })), + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = _Merge; \ No newline at end of file diff --git a/lib/layers/merge/index.js b/lib/layers/merge/index.js new file mode 100644 index 0000000000..92e1fc1927 --- /dev/null +++ b/lib/layers/merge/index.js @@ -0,0 +1,71 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "Add", { + enumerable: true, + get: function () { + return _Add.default; + } +}); +Object.defineProperty(exports, "Subtract", { + enumerable: true, + get: function () { + return _Subtract.default; + } +}); +Object.defineProperty(exports, "Multiply", { + enumerable: true, + get: function () { + return _Multiply.default; + } +}); +Object.defineProperty(exports, "Average", { + enumerable: true, + get: function () { + return _Average.default; + } +}); +Object.defineProperty(exports, "Maximum", { + enumerable: true, + get: function () { + return _Maximum.default; + } +}); +Object.defineProperty(exports, "Minimum", { + enumerable: true, + get: function () { + return _Minimum.default; + } +}); +Object.defineProperty(exports, "Concatenate", { + enumerable: true, + get: function () { + return _Concatenate.default; + } +}); +Object.defineProperty(exports, "Dot", { + enumerable: true, + get: function () { + return _Dot.default; + } +}); + +var _Add = _interopRequireDefault(require("./Add")); + +var _Subtract = _interopRequireDefault(require("./Subtract")); + +var _Multiply = _interopRequireDefault(require("./Multiply")); + +var _Average = _interopRequireDefault(require("./Average")); + +var _Maximum = _interopRequireDefault(require("./Maximum")); + +var _Minimum = _interopRequireDefault(require("./Minimum")); + +var _Concatenate = _interopRequireDefault(require("./Concatenate")); + +var _Dot = _interopRequireDefault(require("./Dot")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/noise/GaussianDropout.js b/lib/layers/noise/GaussianDropout.js new file mode 100644 index 0000000000..2eeefe7648 --- /dev/null +++ b/lib/layers/noise/GaussianDropout.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GaussianDropout extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GaussianDropout'; + const { + rate = 0.5 + } = attrs; + this.rate = Math.min(Math.max(0, rate), 1); + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = GaussianDropout; \ No newline at end of file diff --git a/lib/layers/noise/GaussianNoise.js b/lib/layers/noise/GaussianNoise.js new file mode 100644 index 0000000000..d8a7e7de58 --- /dev/null +++ b/lib/layers/noise/GaussianNoise.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GaussianNoise extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GaussianNoise'; + const { + stddev = 0 + } = attrs; + this.stddev = stddev; + } + + call(x) { + this.output = x; + return this.output; + } + +} + +exports.default = GaussianNoise; \ No newline at end of file diff --git a/lib/layers/noise/index.js b/lib/layers/noise/index.js new file mode 100644 index 0000000000..74e2a4a66c --- /dev/null +++ b/lib/layers/noise/index.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "GaussianDropout", { + enumerable: true, + get: function () { + return _GaussianDropout.default; + } +}); +Object.defineProperty(exports, "GaussianNoise", { + enumerable: true, + get: function () { + return _GaussianNoise.default; + } +}); + +var _GaussianDropout = _interopRequireDefault(require("./GaussianDropout")); + +var _GaussianNoise = _interopRequireDefault(require("./GaussianNoise")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/normalization/BatchNormalization.js b/lib/layers/normalization/BatchNormalization.js new file mode 100644 index 0000000000..d3d7dffbff --- /dev/null +++ b/lib/layers/normalization/BatchNormalization.js @@ -0,0 +1,272 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const programSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D X;\r\nuniform isampler2D normAxisIndexMap;\r\nuniform sampler2D gamma;\r\nuniform sampler2D beta;\r\nuniform sampler2D mean;\r\nuniform sampler2D std;\r\nuniform float epsilon;\r\nuniform bool scale;\r\nuniform bool center;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(X, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\nint normAxisIndex = texelFetch(normAxisIndexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n float _x = texelFetch(X, ivec2(out_x, out_y), 0).r;\r\n float _mean = texelFetch(mean, ivec2(normAxisIndex, 0), 0).r;\r\n float _std = texelFetch(std, ivec2(normAxisIndex, 0), 0).r;\r\n\r\n float _gamma = 1.0;\r\n if (scale) {\r\n _gamma = texelFetch(gamma, ivec2(normAxisIndex, 0), 0).r;\r\n }\r\n\r\n float _beta = 0.0;\r\n if (center) {\r\n _beta = texelFetch(beta, ivec2(normAxisIndex, 0), 0).r;\r\n }\r\n\r\n float sum = _beta + _gamma * (_x - _mean) / sqrt(_std + epsilon);\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + +class BatchNormalization extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'BatchNormalization'; + const { + epsilon = 0.001, + axis = -1, + center = true, + scale = true + } = attrs; + this.epsilon = epsilon; + this.center = center; + this.scale = scale; + this.axis = axis; + this.axisNormalized = false; + this.params = []; + + if (this.scale) { + this.params.push('gamma'); + } + + if (this.center) { + this.params.push('beta'); + } + + this.params = this.params.concat(['moving_mean', 'moving_variance']); + + if (this.gpu) { + this.program = _WebGL.webgl2.compileProgram(programSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (!this.axisNormalized) { + this.axis = this.axis < 0 ? x.tensor.shape.length + this.axis : this.axis - 1; + this.axisNormalized = true; + } + + let broadcast = []; + + for (let d = 0; d < x.tensor.shape.length; d++) { + if (d === this.axis) broadcast.push(1);else broadcast.push(null); + } + + let _gamma = new _Tensor.default([], x.tensor.shape); + + let _beta = new _Tensor.default([], x.tensor.shape); + + for (let i = 0; i < x.tensor.shape[this.axis]; i++) { + broadcast[this.axis] = i; + + if (this.scale) { + _ndarrayOps.default.assigns(_gamma.tensor.pick(...broadcast), this.weights['gamma'].tensor.get(i)); + } + + if (this.center) { + _ndarrayOps.default.assigns(_beta.tensor.pick(...broadcast), this.weights['beta'].tensor.get(i)); + } + } + + let _mean = new _Tensor.default([], x.tensor.shape); + + let _std = new _Tensor.default([], x.tensor.shape); + + for (let i = 0; i < x.tensor.shape[this.axis]; i++) { + broadcast[this.axis] = i; + + _ndarrayOps.default.assigns(_mean.tensor.pick(...broadcast), this.weights['moving_mean'].tensor.get(i)); + + _ndarrayOps.default.assigns(_std.tensor.pick(...broadcast), this.weights['moving_variance'].tensor.get(i) + this.epsilon); + } + + _ndarrayOps.default.sqrteq(_std.tensor); + + this.output = new _Tensor.default(x.tensor.data, x.tensor.shape); + + _ndarrayOps.default.subeq(this.output.tensor, _mean.tensor); + + _ndarrayOps.default.diveq(this.output.tensor, _std.tensor); + + if (this.scale) { + _ndarrayOps.default.muleq(this.output.tensor, _gamma.tensor); + } + + if (this.center) { + _ndarrayOps.default.addeq(this.output.tensor, _beta.tensor); + } + } + + _createIndexMap(glTextureShape, indicesForReshaped) { + if (this.normAxisIndexMap) { + return; + } + + const _normAxisIndexMap = new _Tensor.default([], this.inputShape, { + type: Int32Array + }); + + this.normAxisIndexMap = new _Tensor.default([], glTextureShape, { + type: Int32Array + }); + const slice = Array(this.inputShape.length).fill(null); + + for (let i = 0; i < this.inputShape[this.axis]; i++) { + slice[this.axis] = i; + + _ndarrayOps.default.assigns(_normAxisIndexMap.tensor.pick(...slice), i); + } + + if (indicesForReshaped) { + for (let i = 0; i < indicesForReshaped.data.length; i++) { + this.normAxisIndexMap.tensor.data[indicesForReshaped.data[i]] = _normAxisIndexMap.tensor.data[i]; + } + } else { + this.normAxisIndexMap = _normAxisIndexMap; + } + + this.normAxisIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (!this.axisNormalized) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + + this.axis = this.axis < 0 ? this.inputShape.length + this.axis : this.axis - 1; + this.axisNormalized = true; + } + + if (!x.glTexture && !x.glTextureFragments) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + } + + this._createIndexMap(x.glTextureShape, x.indicesForReshaped); + + if (!this.output) { + this.output = new _Tensor.default([], x.glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (x.is1D) { + this.output.is1D = x.is1D; + } else if (x.is2DReshaped || x.is2DSquareReshaped) { + if (x.is2DReshaped) { + this.output.is2DReshaped = x.is2DReshaped; + } else if (x.is2DSquareReshaped) { + this.output.is2DSquareReshaped = x.is2DSquareReshaped; + } + + this.output.originalShape = x.originalShape; + this.output.indicesForReshaped = x.indicesForReshaped; + } + } + + const programInputs = [{ + input: x, + name: 'X' + }, { + input: this.normAxisIndexMap, + name: 'normAxisIndexMap' + }]; + + if (this.scale) { + programInputs.push({ + input: this.weights['gamma'], + name: 'gamma' + }); + } + + if (this.center) { + programInputs.push({ + input: this.weights['beta'], + name: 'beta' + }); + } + + programInputs.push({ + input: this.weights['moving_mean'], + name: 'mean' + }); + programInputs.push({ + input: this.weights['moving_variance'], + name: 'std' + }); + const programUniforms = [{ + value: this.epsilon, + type: 'float', + name: 'epsilon' + }, { + value: +this.scale, + type: 'bool', + name: 'scale' + }, { + value: +this.center, + type: 'bool', + name: 'center' + }]; + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: programInputs, + uniforms: programUniforms, + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = BatchNormalization; \ No newline at end of file diff --git a/lib/layers/normalization/index.js b/lib/layers/normalization/index.js new file mode 100644 index 0000000000..7985bce8aa --- /dev/null +++ b/lib/layers/normalization/index.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "BatchNormalization", { + enumerable: true, + get: function () { + return _BatchNormalization.default; + } +}); + +var _BatchNormalization = _interopRequireDefault(require("./BatchNormalization")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/pooling/AveragePooling1D.js b/lib/layers/pooling/AveragePooling1D.js new file mode 100644 index 0000000000..0ddbe25d2c --- /dev/null +++ b/lib/layers/pooling/AveragePooling1D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling1D2 = _interopRequireDefault(require("./_Pooling1D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AveragePooling1D extends _Pooling1D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'AveragePooling1D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = AveragePooling1D; \ No newline at end of file diff --git a/lib/layers/pooling/AveragePooling2D.js b/lib/layers/pooling/AveragePooling2D.js new file mode 100644 index 0000000000..b22880d9f8 --- /dev/null +++ b/lib/layers/pooling/AveragePooling2D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling2D2 = _interopRequireDefault(require("./_Pooling2D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AveragePooling2D extends _Pooling2D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'AveragePooling2D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = AveragePooling2D; \ No newline at end of file diff --git a/lib/layers/pooling/AveragePooling3D.js b/lib/layers/pooling/AveragePooling3D.js new file mode 100644 index 0000000000..a54a3e2d0b --- /dev/null +++ b/lib/layers/pooling/AveragePooling3D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling3D2 = _interopRequireDefault(require("./_Pooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class AveragePooling3D extends _Pooling3D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'AveragePooling3D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = AveragePooling3D; \ No newline at end of file diff --git a/lib/layers/pooling/GlobalAveragePooling1D.js b/lib/layers/pooling/GlobalAveragePooling1D.js new file mode 100644 index 0000000000..741125c09c --- /dev/null +++ b/lib/layers/pooling/GlobalAveragePooling1D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling1D2 = _interopRequireDefault(require("./_GlobalPooling1D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalAveragePooling1D extends _GlobalPooling1D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalAveragePooling1D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = GlobalAveragePooling1D; \ No newline at end of file diff --git a/lib/layers/pooling/GlobalAveragePooling2D.js b/lib/layers/pooling/GlobalAveragePooling2D.js new file mode 100644 index 0000000000..195f3a3787 --- /dev/null +++ b/lib/layers/pooling/GlobalAveragePooling2D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling2D2 = _interopRequireDefault(require("./_GlobalPooling2D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalAveragePooling2D extends _GlobalPooling2D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalAveragePooling2D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = GlobalAveragePooling2D; \ No newline at end of file diff --git a/lib/layers/pooling/GlobalAveragePooling3D.js b/lib/layers/pooling/GlobalAveragePooling3D.js new file mode 100644 index 0000000000..9c9c95e6a6 --- /dev/null +++ b/lib/layers/pooling/GlobalAveragePooling3D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling3D2 = _interopRequireDefault(require("./_GlobalPooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalAveragePooling3D extends _GlobalPooling3D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalAveragePooling3D'; + this.poolingFunc = 'average'; + } + +} + +exports.default = GlobalAveragePooling3D; \ No newline at end of file diff --git a/lib/layers/pooling/GlobalMaxPooling1D.js b/lib/layers/pooling/GlobalMaxPooling1D.js new file mode 100644 index 0000000000..bbc6871b6b --- /dev/null +++ b/lib/layers/pooling/GlobalMaxPooling1D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling1D2 = _interopRequireDefault(require("./_GlobalPooling1D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalMaxPooling1D extends _GlobalPooling1D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalMaxPooling1D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = GlobalMaxPooling1D; \ No newline at end of file diff --git a/lib/layers/pooling/GlobalMaxPooling2D.js b/lib/layers/pooling/GlobalMaxPooling2D.js new file mode 100644 index 0000000000..532eed4613 --- /dev/null +++ b/lib/layers/pooling/GlobalMaxPooling2D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling2D2 = _interopRequireDefault(require("./_GlobalPooling2D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalMaxPooling2D extends _GlobalPooling2D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalMaxPooling2D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = GlobalMaxPooling2D; \ No newline at end of file diff --git a/lib/layers/pooling/GlobalMaxPooling3D.js b/lib/layers/pooling/GlobalMaxPooling3D.js new file mode 100644 index 0000000000..cd7de61e57 --- /dev/null +++ b/lib/layers/pooling/GlobalMaxPooling3D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _GlobalPooling3D2 = _interopRequireDefault(require("./_GlobalPooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class GlobalMaxPooling3D extends _GlobalPooling3D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'GlobalMaxPooling3D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = GlobalMaxPooling3D; \ No newline at end of file diff --git a/lib/layers/pooling/MaxPooling1D.js b/lib/layers/pooling/MaxPooling1D.js new file mode 100644 index 0000000000..01b7d1c47a --- /dev/null +++ b/lib/layers/pooling/MaxPooling1D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling1D2 = _interopRequireDefault(require("./_Pooling1D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class MaxPooling1D extends _Pooling1D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'MaxPooling1D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = MaxPooling1D; \ No newline at end of file diff --git a/lib/layers/pooling/MaxPooling2D.js b/lib/layers/pooling/MaxPooling2D.js new file mode 100644 index 0000000000..814efd789d --- /dev/null +++ b/lib/layers/pooling/MaxPooling2D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling2D2 = _interopRequireDefault(require("./_Pooling2D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class MaxPooling2D extends _Pooling2D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'MaxPooling2D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = MaxPooling2D; \ No newline at end of file diff --git a/lib/layers/pooling/MaxPooling3D.js b/lib/layers/pooling/MaxPooling3D.js new file mode 100644 index 0000000000..0815b92973 --- /dev/null +++ b/lib/layers/pooling/MaxPooling3D.js @@ -0,0 +1,21 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Pooling3D2 = _interopRequireDefault(require("./_Pooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class MaxPooling3D extends _Pooling3D2.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'MaxPooling3D'; + this.poolingFunc = 'max'; + } + +} + +exports.default = MaxPooling3D; \ No newline at end of file diff --git a/lib/layers/pooling/_GlobalPooling1D.js b/lib/layers/pooling/_GlobalPooling1D.js new file mode 100644 index 0000000000..43020e2b16 --- /dev/null +++ b/lib/layers/pooling/_GlobalPooling1D.js @@ -0,0 +1,103 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +class _GlobalPooling1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_GlobalPooling1D'; + const { + data_format = 'channels_last' + } = attrs; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const [steps, features] = x.tensor.shape; + this.output = new _Tensor.default([], [features]); + + for (let i = 0, len = features; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, _ndarrayOps.default.sup(x.tensor.pick(null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, _ndarrayOps.default.sum(x.tensor.pick(null, i)) / steps); + } + } + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + + if (!this.output) { + this.output = new _Tensor.default([], [this.inputShape[1]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const isMaxPooling = this.poolingFunc === 'max'; + + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = _GlobalPooling1D; \ No newline at end of file diff --git a/lib/layers/pooling/_GlobalPooling2D.js b/lib/layers/pooling/_GlobalPooling2D.js new file mode 100644 index 0000000000..db587281c3 --- /dev/null +++ b/lib/layers/pooling/_GlobalPooling2D.js @@ -0,0 +1,113 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +class _GlobalPooling2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_GlobalPooling2D'; + const { + data_format = 'channels_last' + } = attrs; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + const [rows, cols, channels] = x.tensor.shape; + this.output = new _Tensor.default([], [channels]); + + for (let i = 0, len = channels; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, _ndarrayOps.default.sup(x.tensor.pick(null, null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, _ndarrayOps.default.sum(x.tensor.pick(null, null, i)) / (rows * cols)); + } + } + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [this.inputShape[2]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const isMaxPooling = this.poolingFunc === 'max'; + + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0] * this.inputShape[1], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = _GlobalPooling2D; \ No newline at end of file diff --git a/lib/layers/pooling/_GlobalPooling3D.js b/lib/layers/pooling/_GlobalPooling3D.js new file mode 100644 index 0000000000..7aaa74e696 --- /dev/null +++ b/lib/layers/pooling/_GlobalPooling3D.js @@ -0,0 +1,113 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +class _GlobalPooling3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_GlobalPooling3D'; + const { + data_format = 'channels_last' + } = attrs; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + const [dim1, dim2, dim3, channels] = x.tensor.shape; + this.output = new _Tensor.default([], [channels]); + + for (let i = 0, len = channels; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, _ndarrayOps.default.sup(x.tensor.pick(null, null, null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, _ndarrayOps.default.sum(x.tensor.pick(null, null, null, i)) / (dim1 * dim2 * dim3)); + } + } + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new _Tensor.default([], [this.inputShape[3]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const isMaxPooling = this.poolingFunc === 'max'; + + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0] * this.inputShape[1] * this.inputShape[2], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = _GlobalPooling3D; \ No newline at end of file diff --git a/lib/layers/pooling/_Pooling1D.js b/lib/layers/pooling/_Pooling1D.js new file mode 100644 index 0000000000..59fa7bfadd --- /dev/null +++ b/lib/layers/pooling/_Pooling1D.js @@ -0,0 +1,210 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +const poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +class _Pooling1D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_Pooling1D'; + const { + pool_size = 2, + strides = null, + padding = 'valid' + } = attrs; + this.poolSize = pool_size; + this.strides = strides === null ? this.poolSize : strides; + this.padding = padding; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + this.poolingFragmentsProgram = _WebGL.webgl2.compileProgram(poolingFragmentsProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const stepsNew = this.padding === 'valid' ? Math.floor((x.tensor.shape[0] - this.poolSize + this.strides) / this.strides) : Math.floor((x.tensor.shape[0] + this.strides - 1) / this.strides); + this.output = new _Tensor.default([], [stepsNew, x.tensor.shape[1]]); + const outputStep = new _Tensor.default([], [x.tensor.shape[1]]); + let step = this.padding === 'valid' ? 0 : Math.min(0, Math.ceil((x.tensor.shape[0] - (stepsNew - 1) * this.strides - this.poolSize) / 2)); + + for (let i = 0; i < stepsNew; i++) { + let _step = Math.max(0, step); + + let limit = this.poolSize + Math.min(0, step); + + _ndarrayOps.default.assign(outputStep.tensor, x.tensor.pick(_step, null)); + + let count = 1; + + for (let j = 1; j < limit; j++) { + if (_step + j > x.tensor.shape[0] - 1) { + break; + } + + if (this.poolingFunc === 'max') { + _ndarrayOps.default.maxeq(outputStep.tensor, x.tensor.pick(_step + j, null)); + } else if (this.poolingFunc === 'average') { + _ndarrayOps.default.addeq(outputStep.tensor, x.tensor.pick(_step + j, null)); + } + + count += 1; + } + + if (this.poolingFunc === 'average') { + _ndarrayOps.default.divseq(outputStep.tensor, count); + } + + _ndarrayOps.default.assign(this.output.tensor.pick(i, null), outputStep.tensor); + + step += this.strides; + } + } + + _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + const stepsNew = this.padding === 'valid' ? Math.floor((this.inputShape[0] - this.poolSize + this.strides) / this.strides) : Math.floor((this.inputShape[0] + this.strides - 1) / this.strides); + this.outputShape = [stepsNew, this.inputShape[1]]; + this.poolIndexMap = new _Tensor.default([], [stepsNew, this.poolSize], { + type: Int32Array + }); + + _ndarrayOps.default.assigns(this.poolIndexMap.tensor, -1); + + let step = this.padding === 'valid' ? 0 : Math.min(0, Math.ceil((this.inputShape[0] - (stepsNew - 1) * this.strides - this.poolSize) / 2)); + + for (let i = 0; i < stepsNew; i++) { + let _step = Math.max(0, step); + + let limit = this.poolSize + Math.min(0, step); + let inputIndex = _step; + this.poolIndexMap.tensor.set(i, 0, inputIndex); + + for (let j = 1; j < limit; j++) { + inputIndex = _step + j; + + if (inputIndex <= this.inputShape[0] - 1) { + this.poolIndexMap.tensor.set(i, j, inputIndex); + } else { + break; + } + } + + step += this.strides; + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this.inputShape = x.tensor.shape; + + this._createIndexMap(); + + if (!this.output) { + this.output = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + const isMaxPooling = this.poolingFunc === 'max'; + const programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: this.poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (x.glTextureFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + + _WebGL.webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + + x.removeGLTextureFragmentsAsColStack(); + } else { + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = _Pooling1D; \ No newline at end of file diff --git a/lib/layers/pooling/_Pooling2D.js b/lib/layers/pooling/_Pooling2D.js new file mode 100644 index 0000000000..4e3641f00e --- /dev/null +++ b/lib/layers/pooling/_Pooling2D.js @@ -0,0 +1,338 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +const poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +class _Pooling2D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_Pooling2D'; + const { + pool_size = [2, 2], + strides = null, + padding = 'valid', + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(pool_size)) { + this.poolSize = pool_size; + } else { + this.poolSize = [pool_size, pool_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else if (strides !== null) { + this.strides = [strides, strides]; + } else { + this.strides = this.poolSize; + } + + this.padding = padding; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + this.poolingFragmentsProgram = _WebGL.webgl2.compileProgram(poolingFragmentsProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + const [inputRows, inputCols, inputChannels] = inputShape; + const [nbRow, nbCol] = this.poolSize; + const outputRows = this.padding === 'same' ? Math.floor((inputRows + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputRows - nbRow + this.strides[0]) / this.strides[0]); + const outputCols = this.padding === 'same' ? Math.floor((inputCols + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputCols - nbCol + this.strides[1]) / this.strides[1]); + const paddingRow = this.padding === 'same' ? Math.max(0, Math.floor((outputRows - 1) * this.strides[0] + nbRow - inputRows)) : 0; + const paddingCol = this.padding === 'same' ? Math.max(0, Math.floor((outputCols - 1) * this.strides[1] + nbCol - inputCols)) : 0; + const paddingRowBefore = Math.floor(paddingRow / 2); + const paddingRowAfter = paddingRow - paddingRowBefore; + const paddingColBefore = Math.floor(paddingCol / 2); + const paddingColAfter = paddingCol - paddingColBefore; + this.outputShape = [outputRows, outputCols, inputChannels]; + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]; + } + + _padInput(x) { + if (this.padding === 'same') { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + const newRows = inputRows + paddingRowBefore + paddingRowAfter; + const newCols = inputCols + paddingColBefore + paddingColAfter; + + const _x = new _Tensor.default([], [newRows, newCols, inputChannels]); + + if (this.poolingFunc === 'max') { + _ndarrayOps.default.assigns(_x.tensor, Number.NEGATIVE_INFINITY); + } + + _ndarrayOps.default.assign(_x.tensor.hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels).lo(paddingRowBefore, paddingColBefore, 0), x.tensor); + + return _x; + } + + return x; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this._calcOutputShape(x.tensor.shape); + + x = this._padInput(x); + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + const [nbRow, nbCol] = this.poolSize; + this.output = new _Tensor.default([], this.outputShape); + const patch = new _Tensor.default([], [nbRow, nbCol, inputChannels]); + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + + for (let i = 0, _i = 0; i <= inputRows - nbRow; i += this.strides[0], _i++) { + let nbRowInPadding = 0; + + if (i < paddingRowBefore) { + nbRowInPadding = paddingRowBefore - i; + } else if (i + nbRow > inputRows - paddingRowAfter) { + nbRowInPadding = i + nbRow - (inputRows - paddingRowAfter); + } + + for (let j = 0, _j = 0; j <= inputCols - nbCol; j += this.strides[1], _j++) { + let nbColInPadding = 0; + + if (j < paddingColBefore) { + nbColInPadding = paddingColBefore - j; + } else if (j + nbCol > inputCols - paddingColAfter) { + nbColInPadding = j + nbCol - (inputCols - paddingColAfter); + } + + const nbCellsEffective = (nbRow - nbRowInPadding) * (nbCol - nbColInPadding); + + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + nbRow, j + nbCol, inputChannels).lo(i, j, 0)); + + for (let c = 0; c < inputChannels; c++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(_i, _j, c, _ndarrayOps.default.sup(patch.tensor.pick(null, null, c))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(_i, _j, c, _ndarrayOps.default.sum(patch.tensor.pick(null, null, c)) / nbCellsEffective); + } + } + } + } + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + + _im2col(x) { + const [inputRows, inputCols, inputChannels] = x.tensor.shape; + + if (!this.tiledInput) { + this.tiledInput = new _Tensor.default([], [inputRows * inputCols, inputChannels]); + } + + const patch = new _Tensor.default([], [inputRows, inputCols]); + const patchRaveled = new _Tensor.default([], [inputRows * inputCols]); + + for (let c = 0; c < inputChannels; c++) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.pick(null, null, c)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.tiledInput.tensor.pick(null, c), patchRaveled.tensor); + } + + return this.tiledInput; + } + + _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + let inputRows = this.inputShape[0]; + let inputCols = this.inputShape[1]; + const rowIndices = new _Tensor.default([], [inputRows, inputCols]); + let index = 0; + + for (let i = 0; i < inputRows; i++) { + for (let j = 0; j < inputCols; j++) { + rowIndices.tensor.set(i, j, index); + index += 1; + } + } + + if (this.padding === 'same') { + const [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter] = this.inputPadding; + inputRows = inputRows + paddingRowBefore + paddingRowAfter; + inputCols = inputCols + paddingColBefore + paddingColAfter; + + const _rowIndices = new _Tensor.default([], [inputRows, inputCols]); + + _ndarrayOps.default.assigns(_rowIndices.tensor, -1); + + _ndarrayOps.default.assign(_rowIndices.tensor.hi(this.inputShape[0] + paddingRowBefore, this.inputShape[1] + paddingColBefore).lo(paddingRowBefore, paddingColBefore), rowIndices.tensor); + + rowIndices.tensor = _rowIndices.tensor; + } + + const [nbRow, nbCol] = this.poolSize; + const outputRows = this.outputShape[0]; + const outputCols = this.outputShape[1]; + this.poolIndexMap = new _Tensor.default([], [outputRows * outputCols, nbRow * nbCol], { + type: Int32Array + }); + const patchRow = new _Tensor.default([], [nbRow, nbCol]); + let offset = 0; + + for (let i = 0, limit = inputRows - nbRow; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputCols - nbCol; j <= limit; j += this.strides[1]) { + _ndarrayOps.default.assign(patchRow.tensor, rowIndices.tensor.hi(i + nbRow, j + nbCol).lo(i, j)); + + this.poolIndexMap.tensor.data.set(patchRow.tensor.data, offset); + offset += nbRow * nbCol; + } + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + + this._im2col(x); + + this.tiledInput.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(); + + if (!this.output) { + const [outputRows, outputCols, inputChannels] = this.outputShape; + const outputTextureShape = [outputRows * outputCols, inputChannels]; + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.tiledInput; + const poolSize = this.poolSize[0] * this.poolSize[1]; + const isMaxPooling = this.poolingFunc === 'max'; + const programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (input.glTextureFragments) { + input.convert2DRowFragmentedGLTextureToColStack(); + + _WebGL.webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + + input.removeGLTextureFragmentsAsColStack(); + } else { + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + +} + +exports.default = _Pooling2D; \ No newline at end of file diff --git a/lib/layers/pooling/_Pooling3D.js b/lib/layers/pooling/_Pooling3D.js new file mode 100644 index 0000000000..652882cf74 --- /dev/null +++ b/lib/layers/pooling/_Pooling3D.js @@ -0,0 +1,359 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var tensorUtils = _interopRequireWildcard(require("../../utils/tensorUtils")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +const poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +class _Pooling3D extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = '_Pooling3D'; + const { + pool_size = [2, 2, 2], + strides = null, + padding = 'valid', + data_format = 'channels_last' + } = attrs; + + if (Array.isArray(pool_size)) { + this.poolSize = pool_size; + } else { + this.poolSize = [pool_size, pool_size, pool_size]; + } + + if (Array.isArray(strides)) { + this.strides = strides; + } else if (strides !== null) { + this.strides = [strides, strides, strides]; + } else { + this.strides = this.poolSize; + } + + this.padding = padding; + this.dataFormat = data_format; + this.poolingFunc = 'max'; + + if (this.gpu) { + this.poolingProgram = _WebGL.webgl2.compileProgram(poolingProgramSource); + this.poolingFragmentsProgram = _WebGL.webgl2.compileProgram(poolingFragmentsProgramSource); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + const [inputDim1, inputDim2, inputDim3, inputChannels] = inputShape; + const [poolDim1, poolDim2, poolDim3] = this.poolSize; + const outputDim1 = this.padding === 'same' ? Math.floor((inputDim1 + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputDim1 - poolDim1 + this.strides[0]) / this.strides[0]); + const outputDim2 = this.padding === 'same' ? Math.floor((inputDim2 + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputDim2 - poolDim2 + this.strides[1]) / this.strides[1]); + const outputDim3 = this.padding === 'same' ? Math.floor((inputDim3 + this.strides[2] - 1) / this.strides[2]) : Math.floor((inputDim3 - poolDim3 + this.strides[2]) / this.strides[2]); + const paddingDim1 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim1 - 1) * this.strides[0] + poolDim1 - inputDim1)) : 0; + const paddingDim2 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim2 - 1) * this.strides[1] + poolDim2 - inputDim2)) : 0; + const paddingDim3 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim3 - 1) * this.strides[2] + poolDim3 - inputDim3)) : 0; + const paddingDim1Before = Math.floor(paddingDim1 / 2); + const paddingDim1After = paddingDim1 - paddingDim1Before; + const paddingDim2Before = Math.floor(paddingDim2 / 2); + const paddingDim2After = paddingDim2 - paddingDim2Before; + const paddingDim3Before = Math.floor(paddingDim3 / 2); + const paddingDim3After = paddingDim3 - paddingDim3Before; + this.outputShape = [outputDim1, outputDim2, outputDim3, inputChannels]; + this.inputPadding = [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After]; + } + + _padInput(x) { + if (this.padding === 'same') { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + const newDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + const newDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + const newDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + + const _x = new _Tensor.default([], [newDim1, newDim2, newDim3, inputChannels]); + + if (this.poolingFunc === 'max') { + _ndarrayOps.default.assigns(_x.tensor, Number.NEGATIVE_INFINITY); + } + + _ndarrayOps.default.assign(_x.tensor.hi(inputDim1 + paddingDim1Before, inputDim2 + paddingDim2Before, inputDim3 + paddingDim3Before, inputChannels).lo(paddingDim1Before, paddingDim2Before, paddingDim3Before, 0), x.tensor); + + return _x; + } + + return x; + } + + _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this._calcOutputShape(x.tensor.shape); + + x = this._padInput(x); + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + const [poolDim1, poolDim2, poolDim3] = this.poolSize; + this.output = new _Tensor.default([], this.outputShape); + let patch = new _Tensor.default([], [poolDim1, poolDim2, poolDim3, inputChannels]); + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + + for (let i = 0, _i = 0; i <= inputDim1 - poolDim1; i += this.strides[0], _i++) { + let dim1InPadding = 0; + + if (i < paddingDim1Before) { + dim1InPadding = paddingDim1Before - i; + } else if (i + poolDim1 > inputDim1 - paddingDim1After) { + dim1InPadding = i + poolDim1 - (inputDim1 - paddingDim1After); + } + + for (let j = 0, _j = 0; j <= inputDim2 - poolDim2; j += this.strides[1], _j++) { + let dim2InPadding = 0; + + if (j < paddingDim2Before) { + dim2InPadding = paddingDim2Before - j; + } else if (j + poolDim2 > inputDim2 - paddingDim2After) { + dim2InPadding = j + poolDim2 - (inputDim2 - paddingDim2After); + } + + for (let k = 0, _k = 0; k <= inputDim3 - poolDim3; k += this.strides[2], _k++) { + let dim3InPadding = 0; + + if (k < paddingDim3Before) { + dim3InPadding = paddingDim3Before - k; + } else if (k + poolDim3 > inputDim3 - paddingDim3After) { + dim3InPadding = k + poolDim3 - (inputDim3 - paddingDim3After); + } + + const nbCellsEffective = (poolDim1 - dim1InPadding) * (poolDim2 - dim2InPadding) * (poolDim3 - dim3InPadding); + + _ndarrayOps.default.assign(patch.tensor, x.tensor.hi(i + poolDim1, j + poolDim2, k + poolDim3, inputChannels).lo(i, j, k, 0)); + + for (let c = 0; c < inputChannels; c++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(_i, _j, _k, c, _ndarrayOps.default.sup(patch.tensor.pick(null, null, null, c))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(_i, _j, _k, c, _ndarrayOps.default.sum(patch.tensor.pick(null, null, null, c)) / nbCellsEffective); + } + } + } + } + } + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + + _vol2col(x) { + const [inputDim1, inputDim2, inputDim3, inputChannels] = x.tensor.shape; + + if (!this.tiledInput) { + this.tiledInput = new _Tensor.default([], [inputDim1 * inputDim2 * inputDim3, inputChannels]); + } + + const patch = new _Tensor.default([], [inputDim1, inputDim2, inputDim3]); + const patchRaveled = new _Tensor.default([], [inputDim1 * inputDim2 * inputDim3]); + + for (let c = 0; c < inputChannels; c++) { + _ndarrayOps.default.assign(patch.tensor, x.tensor.pick(null, null, null, c)); + + patchRaveled.replaceTensorData(patch.tensor.data); + + _ndarrayOps.default.assign(this.tiledInput.tensor.pick(null, c), patchRaveled.tensor); + } + + return this.tiledInput; + } + + _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + let inputDim1 = this.inputShape[0]; + let inputDim2 = this.inputShape[1]; + let inputDim3 = this.inputShape[2]; + const rowIndices = new _Tensor.default([], [inputDim1, inputDim2, inputDim3]); + let index = 0; + + for (let i = 0; i < inputDim1; i++) { + for (let j = 0; j < inputDim2; j++) { + for (let k = 0; k < inputDim3; k++) { + rowIndices.tensor.set(i, j, k, index); + index += 1; + } + } + } + + if (this.padding === 'same') { + const [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After] = this.inputPadding; + inputDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + inputDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + inputDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + + const _rowIndices = new _Tensor.default([], [inputDim1, inputDim2, inputDim3]); + + _ndarrayOps.default.assigns(_rowIndices.tensor, -1); + + _ndarrayOps.default.assign(_rowIndices.tensor.hi(this.inputShape[0] + paddingDim1Before, this.inputShape[1] + paddingDim2Before, this.inputShape[2] + paddingDim3Before).lo(paddingDim1Before, paddingDim2Before, paddingDim3Before), rowIndices.tensor); + + rowIndices.tensor = _rowIndices.tensor; + } + + const [poolDim1, poolDim2, poolDim3] = this.poolSize; + const outputDim1 = this.outputShape[0]; + const outputDim2 = this.outputShape[1]; + const outputDim3 = this.outputShape[2]; + this.poolIndexMap = new _Tensor.default([], [outputDim1 * outputDim2 * outputDim3, poolDim1 * poolDim2 * poolDim3], { + type: Int32Array + }); + const patchRow = new _Tensor.default([], [poolDim1, poolDim2, poolDim3]); + let offset = 0; + + for (let i = 0, limit = inputDim1 - poolDim1; i <= limit; i += this.strides[0]) { + for (let j = 0, limit = inputDim2 - poolDim2; j <= limit; j += this.strides[1]) { + for (let k = 0, limit = inputDim3 - poolDim3; k <= limit; k += this.strides[2]) { + _ndarrayOps.default.assign(patchRow.tensor, rowIndices.tensor.hi(i + poolDim1, j + poolDim2, k + poolDim3).lo(i, j, k)); + + this.poolIndexMap.tensor.data.set(patchRow.tensor.data, offset); + offset += poolDim1 * poolDim2 * poolDim3; + } + } + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + + this._vol2col(x); + + this.tiledInput.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(); + + if (!this.output) { + const [outputDim1, outputDim2, outputDim3, inputChannels] = this.outputShape; + const outputTextureShape = [outputDim1 * outputDim2 * outputDim3, inputChannels]; + this.output = new _Tensor.default([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = tensorUtils.createIndicesFor2DReshaped(this.outputShape, false, -1); + } + + const input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.tiledInput; + const poolSize = this.poolSize[0] * this.poolSize[1] * this.poolSize[2]; + const isMaxPooling = this.poolingFunc === 'max'; + const programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (input.glTextureFragments) { + input.convert2DRowFragmentedGLTextureToColStack(); + + _WebGL.webgl2.runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + + input.removeGLTextureFragmentsAsColStack(); + } else { + _WebGL.webgl2.runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + } + +} + +exports.default = _Pooling3D; \ No newline at end of file diff --git a/lib/layers/pooling/index.js b/lib/layers/pooling/index.js new file mode 100644 index 0000000000..6774b8b615 --- /dev/null +++ b/lib/layers/pooling/index.js @@ -0,0 +1,103 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "MaxPooling1D", { + enumerable: true, + get: function () { + return _MaxPooling1D.default; + } +}); +Object.defineProperty(exports, "MaxPooling2D", { + enumerable: true, + get: function () { + return _MaxPooling2D.default; + } +}); +Object.defineProperty(exports, "MaxPooling3D", { + enumerable: true, + get: function () { + return _MaxPooling3D.default; + } +}); +Object.defineProperty(exports, "AveragePooling1D", { + enumerable: true, + get: function () { + return _AveragePooling1D.default; + } +}); +Object.defineProperty(exports, "AveragePooling2D", { + enumerable: true, + get: function () { + return _AveragePooling2D.default; + } +}); +Object.defineProperty(exports, "AveragePooling3D", { + enumerable: true, + get: function () { + return _AveragePooling3D.default; + } +}); +Object.defineProperty(exports, "GlobalMaxPooling1D", { + enumerable: true, + get: function () { + return _GlobalMaxPooling1D.default; + } +}); +Object.defineProperty(exports, "GlobalMaxPooling2D", { + enumerable: true, + get: function () { + return _GlobalMaxPooling2D.default; + } +}); +Object.defineProperty(exports, "GlobalMaxPooling3D", { + enumerable: true, + get: function () { + return _GlobalMaxPooling3D.default; + } +}); +Object.defineProperty(exports, "GlobalAveragePooling1D", { + enumerable: true, + get: function () { + return _GlobalAveragePooling1D.default; + } +}); +Object.defineProperty(exports, "GlobalAveragePooling2D", { + enumerable: true, + get: function () { + return _GlobalAveragePooling2D.default; + } +}); +Object.defineProperty(exports, "GlobalAveragePooling3D", { + enumerable: true, + get: function () { + return _GlobalAveragePooling3D.default; + } +}); + +var _MaxPooling1D = _interopRequireDefault(require("./MaxPooling1D")); + +var _MaxPooling2D = _interopRequireDefault(require("./MaxPooling2D")); + +var _MaxPooling3D = _interopRequireDefault(require("./MaxPooling3D")); + +var _AveragePooling1D = _interopRequireDefault(require("./AveragePooling1D")); + +var _AveragePooling2D = _interopRequireDefault(require("./AveragePooling2D")); + +var _AveragePooling3D = _interopRequireDefault(require("./AveragePooling3D")); + +var _GlobalMaxPooling1D = _interopRequireDefault(require("./GlobalMaxPooling1D")); + +var _GlobalMaxPooling2D = _interopRequireDefault(require("./GlobalMaxPooling2D")); + +var _GlobalMaxPooling3D = _interopRequireDefault(require("./GlobalMaxPooling3D")); + +var _GlobalAveragePooling1D = _interopRequireDefault(require("./GlobalAveragePooling1D")); + +var _GlobalAveragePooling2D = _interopRequireDefault(require("./GlobalAveragePooling2D")); + +var _GlobalAveragePooling3D = _interopRequireDefault(require("./GlobalAveragePooling3D")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/recurrent/GRU.js b/lib/layers/recurrent/GRU.js new file mode 100644 index 0000000000..6bf7c72d37 --- /dev/null +++ b/lib/layers/recurrent/GRU.js @@ -0,0 +1,682 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var activations = _interopRequireWildcard(require("../../activations")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _cwise = _interopRequireDefault(require("cwise")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; +const gateSummationProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nuniform sampler2D bias;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(bias, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n float bias_val = texelFetch(bias, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val + t2_val + bias_val);\r\n}\r\n"; +const gateProductProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(t1, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val * t2_val);\r\n}\r\n"; +const timestepReadProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n\r\n outColor = vec4(texelFetch(x, ivec2(out_x, index), 0).r);\r\n}\r\n"; +const timestepWriteProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D y;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(y, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (out_y == index) {\r\n outColor = vec4(texelFetch(x, ivec2(out_x, 0), 0).r);\r\n } else {\r\n outColor = vec4(texelFetch(y, ivec2(out_x, out_y), 0).r);\r\n }\r\n}\r\n"; +const updateProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D h;\r\nuniform sampler2D htm1;\r\nuniform sampler2D z;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(h, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float h_val = texelFetch(h, ivec2(out_x, out_y), 0).r;\r\n float htm1_val = texelFetch(htm1, ivec2(out_x, out_y), 0).r;\r\n float z_val = texelFetch(z, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(h_val * (float(1.0) - z_val) + htm1_val * z_val);\r\n}\r\n"; + +class GRU extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + Object.defineProperty(this, "_combine", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array', 'array'], + body: function (_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b; + } + }) + }); + Object.defineProperty(this, "_update", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array'], + body: function (_h, _htm1, _z) { + _h = _h * (1 - _z) + _htm1 * _z; + } + }) + }); + this.layerClass = 'GRU'; + const { + units = 1, + activation = 'tanh', + use_bias = true, + recurrent_activation = 'hard_sigmoid', + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs; + this.units = units; + this.activation = activation; + this.recurrentActivation = recurrent_activation; + this.activationFunc = activations[activation]; + this.recurrentActivationFunc = activations[recurrent_activation]; + this.use_bias = use_bias; + this.returnSequences = return_sequences; + this.goBackwards = go_backwards; + this.stateful = stateful; + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel']; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + this.recurrentActivationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.recurrentActivation]); + this.gateSummationProgram = _WebGL.webgl2.compileProgram(gateSummationProgramSource); + this.gateProductProgram = _WebGL.webgl2.compileProgram(gateProductProgramSource); + this.timestepReadProgram = _WebGL.webgl2.compileProgram(timestepReadProgramSource); + this.timestepWriteProgram = _WebGL.webgl2.compileProgram(timestepWriteProgramSource); + this.updateProgram = _WebGL.webgl2.compileProgram(updateProgramSource); + } + } + + setWeights(weightsArr) { + super.setWeights(weightsArr); + const shape_W = this.weights['kernel'].tensor.shape; + this.weights['W_z'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_r'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_h'] = new _Tensor.default([], [shape_W[0], this.units]); + + _ndarrayOps.default.assign(this.weights['W_z'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], this.units).lo(0, 0)); + + _ndarrayOps.default.assign(this.weights['W_r'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 2 * this.units).lo(0, this.units)); + + _ndarrayOps.default.assign(this.weights['W_h'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 3 * this.units).lo(0, 2 * this.units)); + + const shape_U = this.weights['recurrent_kernel'].tensor.shape; + this.weights['U_z'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_r'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_h'] = new _Tensor.default([], [shape_U[0], this.units]); + + _ndarrayOps.default.assign(this.weights['U_z'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], this.units).lo(0, 0)); + + _ndarrayOps.default.assign(this.weights['U_r'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 2 * this.units).lo(0, this.units)); + + _ndarrayOps.default.assign(this.weights['U_h'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 3 * this.units).lo(0, 2 * this.units)); + + this.weights['b_z'] = new _Tensor.default([], [this.units]); + this.weights['b_r'] = new _Tensor.default([], [this.units]); + this.weights['b_h'] = new _Tensor.default([], [this.units]); + + if (this.use_bias) { + _ndarrayOps.default.assign(this.weights['b_z'].tensor, this.weights['bias'].tensor.hi(this.units).lo(0)); + + _ndarrayOps.default.assign(this.weights['b_r'].tensor, this.weights['bias'].tensor.hi(2 * this.units).lo(this.units)); + + _ndarrayOps.default.assign(this.weights['b_h'].tensor, this.weights['bias'].tensor.hi(3 * this.units).lo(2 * this.units)); + } + + if (this.gpu) { + const names = ['W_z', 'W_r', 'W_h', 'U_z', 'U_r', 'U_h', 'b_z', 'b_r', 'b_h']; + names.forEach(name => { + this.weights[name].createGLTexture({ + type: '2d', + format: 'float' + }); + }); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const dimUpdateGate = this.weights['b_z'].tensor.shape[0]; + const dimResetGate = this.weights['b_r'].tensor.shape[0]; + const dimHiddenState = this.weights['b_h'].tensor.shape[0]; + const currentUpdateGateState = new _Tensor.default([], [dimUpdateGate]); + const tempXZ = new _Tensor.default([], [dimUpdateGate]); + const tempHZ = new _Tensor.default([], [dimUpdateGate]); + const currentResetGateState = new _Tensor.default([], [dimResetGate]); + const tempXR = new _Tensor.default([], [dimResetGate]); + const tempHR = new _Tensor.default([], [dimResetGate]); + const currentHiddenState = this.stateful && this.currentHiddenState ? this.currentHiddenState : new _Tensor.default([], [dimHiddenState]); + const tempXH = new _Tensor.default([], [dimHiddenState]); + const tempHH = new _Tensor.default([], [dimHiddenState]); + const previousHiddenState = new _Tensor.default([], [dimHiddenState]); + this.hiddenStateSequence = new _Tensor.default([], [x.tensor.shape[0], dimHiddenState]); + const currentX = new _Tensor.default([], [x.tensor.shape[1]]); + + const _step = () => { + _ndarrayOps.default.assign(previousHiddenState.tensor, currentHiddenState.tensor); + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_z'].tensor.transpose(1, 0), currentX.tensor, 1, tempXZ.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_z'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHZ.tensor); + + this._combine(currentUpdateGateState.tensor, tempXZ.tensor, tempHZ.tensor, this.weights['b_z'].tensor); + + this.recurrentActivationFunc(currentUpdateGateState); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_r'].tensor.transpose(1, 0), currentX.tensor, 1, tempXR.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_r'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHR.tensor); + + this._combine(currentResetGateState.tensor, tempXR.tensor, tempHR.tensor, this.weights['b_r'].tensor); + + this.recurrentActivationFunc(currentResetGateState); + + _ndarrayOps.default.muleq(currentResetGateState.tensor, previousHiddenState.tensor); + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_h'].tensor.transpose(1, 0), currentX.tensor, 1, tempXH.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_h'].tensor.transpose(1, 0), currentResetGateState.tensor, 1, tempHH.tensor); + + this._combine(currentHiddenState.tensor, tempXH.tensor, tempHH.tensor, this.weights['b_h'].tensor); + + this.activationFunc(currentHiddenState); + + this._update(currentHiddenState.tensor, previousHiddenState.tensor, currentUpdateGateState.tensor); + }; + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _ndarrayOps.default.assign(currentX.tensor, x.tensor.pick(inputIndex, null)); + + const tempTensors = [tempXZ, tempHZ, tempXR, tempHR, tempXH, tempHH]; + tempTensors.forEach(temp => _ndarrayOps.default.assigns(temp.tensor, 0)); + + _step(); + + if (this.returnSequences) { + _ndarrayOps.default.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = currentHiddenState; + } + + if (this.stateful) { + this.currentHiddenState = currentHiddenState; + } + } + + _stepGPU() { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ + input: this.currentHiddenState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXZ, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_z'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHZ, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_z'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentUpdateGateStatePreactiv, + inputs: [{ + input: this.tempXZ, + name: 't1' + }, { + input: this.tempHZ, + name: 't2' + }, { + input: this.weights['b_z'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentUpdateGateState, + inputs: [{ + input: this.currentUpdateGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentUpdateGateState = this.currentUpdateGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXR, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_r'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHR, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_r'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentResetGateStatePreactiv, + inputs: [{ + input: this.tempXR, + name: 't1' + }, { + input: this.tempHR, + name: 't2' + }, { + input: this.weights['b_r'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentResetGateState, + inputs: [{ + input: this.currentResetGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentResetGateState = this.currentResetGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentResetGateStateCopy, + inputs: [{ + input: this.currentResetGateState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateProductProgram, + output: this.currentResetGateState, + inputs: [{ + input: this.currentResetGateStateCopy, + name: 't1' + }, { + input: this.previousHiddenState, + name: 't2' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXH, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_h'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHH, + inputs: [{ + input: this.currentResetGateState, + name: 'A' + }, { + input: this.weights['U_h'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentHiddenStatePreactiv, + inputs: [{ + input: this.tempXH, + name: 't1' + }, { + input: this.tempHH, + name: 't2' + }, { + input: this.weights['b_h'], + name: 'bias' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.currentHiddenState, + inputs: [{ + input: this.currentHiddenStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentHiddenState = this.currentHiddenStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentHiddenStateCopy, + inputs: [{ + input: this.currentHiddenState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.updateProgram, + output: this.currentHiddenState, + inputs: [{ + input: this.currentHiddenStateCopy, + name: 'h' + }, { + input: this.previousHiddenState, + name: 'htm1' + }, { + input: this.currentUpdateGateState, + name: 'z' + }] + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const dimUpdateGate = this.weights['b_z'].glTextureShape[1]; + const dimResetGate = this.weights['b_r'].glTextureShape[1]; + const dimHiddenState = this.weights['b_h'].glTextureShape[1]; + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentHiddenStateCopy) { + this.currentHiddenStateCopy = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenStateCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentHiddenStatePreactiv) { + this.currentHiddenStatePreactiv = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentUpdateGateState) { + this.currentUpdateGateState = new _Tensor.default([], [dimUpdateGate]); + this.currentUpdateGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentUpdateGateStatePreactiv) { + this.currentUpdateGateStatePreactiv = new _Tensor.default([], [dimUpdateGate]); + this.currentUpdateGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXZ) { + this.tempXZ = new _Tensor.default([], [dimUpdateGate]); + this.tempXZ.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHZ) { + this.tempHZ = new _Tensor.default([], [dimUpdateGate]); + this.tempHZ.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentResetGateState) { + this.currentResetGateState = new _Tensor.default([], [dimResetGate]); + this.currentResetGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentResetGateStateCopy) { + this.currentResetGateStateCopy = new _Tensor.default([], [dimResetGate]); + this.currentResetGateStateCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentResetGateStatePreactiv) { + this.currentResetGateStatePreactiv = new _Tensor.default([], [dimResetGate]); + this.currentResetGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXR) { + this.tempXR = new _Tensor.default([], [dimResetGate]); + this.tempXR.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHR) { + this.tempHR = new _Tensor.default([], [dimResetGate]); + this.tempHR.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXH) { + this.tempXH = new _Tensor.default([], [dimHiddenState]); + this.tempXH.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHH) { + this.tempHH = new _Tensor.default([], [dimHiddenState]); + this.tempHH.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.previousHiddenState) { + this.previousHiddenState = new _Tensor.default([], [dimHiddenState]); + this.previousHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new _Tensor.default([], [x.glTextureShape[0], dimHiddenState]); + this.hiddenStateSequence.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new _Tensor.default([], [x.glTextureShape[0], dimHiddenState]); + this.hiddenStateSequenceCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentX) { + this.currentX = new _Tensor.default([], [x.glTextureShape[1]]); + this.currentX.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _WebGL.webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: inputIndex, + type: 'int', + name: 'index' + }] + }); + + this._stepGPU(); + + if (this.returnSequences) { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ + input: this.hiddenStateSequence, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ + input: this.currentHiddenState, + name: 'x' + }, { + input: this.hiddenStateSequenceCopy, + name: 'y' + }], + uniforms: [{ + value: i, + type: 'int', + name: 'index' + }] + }); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = this.currentHiddenState; + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = GRU; \ No newline at end of file diff --git a/lib/layers/recurrent/LSTM.js b/lib/layers/recurrent/LSTM.js new file mode 100644 index 0000000000..66e38fb29c --- /dev/null +++ b/lib/layers/recurrent/LSTM.js @@ -0,0 +1,833 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var activations = _interopRequireWildcard(require("../../activations")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _cwise = _interopRequireDefault(require("cwise")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; +const gateSummationProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nuniform sampler2D bias;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(bias, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n float bias_val = texelFetch(bias, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val + t2_val + bias_val);\r\n}\r\n"; +const gateProductProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(t1, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val * t2_val);\r\n}\r\n"; +const timestepReadProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n\r\n outColor = vec4(texelFetch(x, ivec2(out_x, index), 0).r);\r\n}\r\n"; +const timestepWriteProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D y;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(y, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (out_y == index) {\r\n outColor = vec4(texelFetch(x, ivec2(out_x, 0), 0).r);\r\n } else {\r\n outColor = vec4(texelFetch(y, ivec2(out_x, out_y), 0).r);\r\n }\r\n}\r\n"; +const updateProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D c;\r\nuniform sampler2D ctm1;\r\nuniform sampler2D i;\r\nuniform sampler2D f;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(c, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float c_val = texelFetch(c, ivec2(out_x, out_y), 0).r;\r\n float ctm1_val = texelFetch(ctm1, ivec2(out_x, out_y), 0).r;\r\n float i_val = texelFetch(i, ivec2(out_x, out_y), 0).r;\r\n float f_val = texelFetch(f, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(c_val * i_val + ctm1_val * f_val);\r\n}\r\n"; + +class LSTM extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + Object.defineProperty(this, "_combine", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array', 'array'], + body: function (_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b; + } + }) + }); + Object.defineProperty(this, "_update", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array', 'array'], + body: function (_c, _ctm1, _i, _f) { + _c = _c * _i + _ctm1 * _f; + } + }) + }); + this.layerClass = 'LSTM'; + const { + units = 1, + activation = 'tanh', + use_bias = true, + recurrent_activation = 'hard_sigmoid', + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs; + this.units = units; + this.activation = activation; + this.recurrentActivation = recurrent_activation; + this.activationFunc = activations[activation]; + this.recurrentActivationFunc = activations[recurrent_activation]; + this.use_bias = use_bias; + this.returnSequences = return_sequences; + this.goBackwards = go_backwards; + this.stateful = stateful; + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel']; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + this.recurrentActivationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.recurrentActivation]); + this.gateSummationProgram = _WebGL.webgl2.compileProgram(gateSummationProgramSource); + this.gateProductProgram = _WebGL.webgl2.compileProgram(gateProductProgramSource); + this.timestepReadProgram = _WebGL.webgl2.compileProgram(timestepReadProgramSource); + this.timestepWriteProgram = _WebGL.webgl2.compileProgram(timestepWriteProgramSource); + this.updateProgram = _WebGL.webgl2.compileProgram(updateProgramSource); + } + } + + setWeights(weightsArr) { + super.setWeights(weightsArr); + const shape_W = this.weights['kernel'].tensor.shape; + this.weights['W_i'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_f'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_c'] = new _Tensor.default([], [shape_W[0], this.units]); + this.weights['W_o'] = new _Tensor.default([], [shape_W[0], this.units]); + + _ndarrayOps.default.assign(this.weights['W_i'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], this.units).lo(0, 0)); + + _ndarrayOps.default.assign(this.weights['W_f'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 2 * this.units).lo(0, this.units)); + + _ndarrayOps.default.assign(this.weights['W_c'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 3 * this.units).lo(0, 2 * this.units)); + + _ndarrayOps.default.assign(this.weights['W_o'].tensor, this.weights['kernel'].tensor.hi(shape_W[0], 4 * this.units).lo(0, 3 * this.units)); + + const shape_U = this.weights['recurrent_kernel'].tensor.shape; + this.weights['U_i'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_f'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_c'] = new _Tensor.default([], [shape_U[0], this.units]); + this.weights['U_o'] = new _Tensor.default([], [shape_U[0], this.units]); + + _ndarrayOps.default.assign(this.weights['U_i'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], this.units).lo(0, 0)); + + _ndarrayOps.default.assign(this.weights['U_f'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 2 * this.units).lo(0, this.units)); + + _ndarrayOps.default.assign(this.weights['U_c'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 3 * this.units).lo(0, 2 * this.units)); + + _ndarrayOps.default.assign(this.weights['U_o'].tensor, this.weights['recurrent_kernel'].tensor.hi(shape_U[0], 4 * this.units).lo(0, 3 * this.units)); + + this.weights['b_i'] = new _Tensor.default([], [this.units]); + this.weights['b_f'] = new _Tensor.default([], [this.units]); + this.weights['b_c'] = new _Tensor.default([], [this.units]); + this.weights['b_o'] = new _Tensor.default([], [this.units]); + + if (this.use_bias) { + _ndarrayOps.default.assign(this.weights['b_i'].tensor, this.weights['bias'].tensor.hi(this.units).lo(0)); + + _ndarrayOps.default.assign(this.weights['b_f'].tensor, this.weights['bias'].tensor.hi(2 * this.units).lo(this.units)); + + _ndarrayOps.default.assign(this.weights['b_c'].tensor, this.weights['bias'].tensor.hi(3 * this.units).lo(2 * this.units)); + + _ndarrayOps.default.assign(this.weights['b_o'].tensor, this.weights['bias'].tensor.hi(4 * this.units).lo(3 * this.units)); + } + + if (this.gpu) { + const names = ['W_i', 'W_f', 'W_c', 'W_o', 'U_i', 'U_f', 'U_c', 'U_o', 'b_i', 'b_f', 'b_c', 'b_o']; + names.forEach(name => { + this.weights[name].createGLTexture({ + type: '2d', + format: 'float' + }); + }); + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const dimInputGate = this.weights['b_i'].tensor.shape[0]; + const dimCandidate = this.weights['b_c'].tensor.shape[0]; + const dimForgetGate = this.weights['b_f'].tensor.shape[0]; + const dimOutputGate = this.weights['b_o'].tensor.shape[0]; + const currentInputGateState = new _Tensor.default([], [dimInputGate]); + const tempXI = new _Tensor.default([], [dimInputGate]); + const tempHI = new _Tensor.default([], [dimInputGate]); + const currentForgetGateState = new _Tensor.default([], [dimForgetGate]); + const tempXF = new _Tensor.default([], [dimForgetGate]); + const tempHF = new _Tensor.default([], [dimForgetGate]); + const currentOutputGateState = new _Tensor.default([], [dimOutputGate]); + const tempXO = new _Tensor.default([], [dimOutputGate]); + const tempHO = new _Tensor.default([], [dimOutputGate]); + const currentCandidate = new _Tensor.default([], [dimCandidate]); + const tempXC = new _Tensor.default([], [dimCandidate]); + const tempHC = new _Tensor.default([], [dimCandidate]); + const previousCandidate = this.stateful && this.previousCandidate ? this.previousCandidate : new _Tensor.default([], [dimCandidate]); + const currentHiddenState = this.stateful && this.currentHiddenState ? this.currentHiddenState : new _Tensor.default([], [dimCandidate]); + const previousHiddenState = new _Tensor.default([], [dimCandidate]); + this.hiddenStateSequence = new _Tensor.default([], [x.tensor.shape[0], dimCandidate]); + const currentX = new _Tensor.default([], [x.tensor.shape[1]]); + + const _step = () => { + _ndarrayOps.default.assign(previousHiddenState.tensor, currentHiddenState.tensor); + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_i'].tensor.transpose(1, 0), currentX.tensor, 1, tempXI.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_i'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHI.tensor); + + this._combine(currentInputGateState.tensor, tempXI.tensor, tempHI.tensor, this.weights['b_i'].tensor); + + this.recurrentActivationFunc(currentInputGateState); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_f'].tensor.transpose(1, 0), currentX.tensor, 1, tempXF.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_f'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHF.tensor); + + this._combine(currentForgetGateState.tensor, tempXF.tensor, tempHF.tensor, this.weights['b_f'].tensor); + + this.recurrentActivationFunc(currentForgetGateState); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_o'].tensor.transpose(1, 0), currentX.tensor, 1, tempXO.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_o'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHO.tensor); + + this._combine(currentOutputGateState.tensor, tempXO.tensor, tempHO.tensor, this.weights['b_o'].tensor); + + this.recurrentActivationFunc(currentOutputGateState); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['W_c'].tensor.transpose(1, 0), currentX.tensor, 1, tempXC.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['U_c'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHC.tensor); + + this._combine(currentCandidate.tensor, tempXC.tensor, tempHC.tensor, this.weights['b_c'].tensor); + + this.activationFunc(currentCandidate); + + this._update(currentCandidate.tensor, previousCandidate.tensor, currentInputGateState.tensor, currentForgetGateState.tensor); + + _ndarrayOps.default.assign(previousCandidate.tensor, currentCandidate.tensor); + + this.activationFunc(currentCandidate); + + _ndarrayOps.default.mul(currentHiddenState.tensor, currentOutputGateState.tensor, currentCandidate.tensor); + }; + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _ndarrayOps.default.assign(currentX.tensor, x.tensor.pick(inputIndex, null)); + + const tempTensors = [tempXI, tempHI, tempXF, tempHF, tempXO, tempHO, tempXC, tempHC]; + tempTensors.forEach(temp => _ndarrayOps.default.assigns(temp.tensor, 0)); + + _step(); + + _ndarrayOps.default.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor); + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = currentHiddenState; + } + + if (this.stateful) { + this.previousCandidate = previousCandidate; + this.currentHiddenState = currentHiddenState; + } + } + + _stepGPU() { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ + input: this.currentHiddenState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXI, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_i'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHI, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_i'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentInputGateStatePreactiv, + inputs: [{ + input: this.tempXI, + name: 't1' + }, { + input: this.tempHI, + name: 't2' + }, { + input: this.weights['b_i'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentInputGateState, + inputs: [{ + input: this.currentInputGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentInputGateState = this.currentInputGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXF, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_f'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHF, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_f'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentForgetGateStatePreactiv, + inputs: [{ + input: this.tempXF, + name: 't1' + }, { + input: this.tempHF, + name: 't2' + }, { + input: this.weights['b_f'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentForgetGateState, + inputs: [{ + input: this.currentForgetGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentForgetGateState = this.currentForgetGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXO, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_o'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHO, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_o'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentOutputGateStatePreactiv, + inputs: [{ + input: this.tempXO, + name: 't1' + }, { + input: this.tempHO, + name: 't2' + }, { + input: this.weights['b_o'], + name: 'bias' + }] + }); + + if (this.recurrentActivation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.recurrentActivationProgram, + output: this.currentOutputGateState, + inputs: [{ + input: this.currentOutputGateStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentOutputGateState = this.currentOutputGateStatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXC, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['W_c'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHC, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['U_c'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentCandidatePreactiv, + inputs: [{ + input: this.tempXC, + name: 't1' + }, { + input: this.tempHC, + name: 't2' + }, { + input: this.weights['b_c'], + name: 'bias' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.currentCandidate, + inputs: [{ + input: this.currentCandidatePreactiv, + name: 'x' + }] + }); + } else { + this.currentCandidate = this.currentCandidatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentCandidateCopy, + inputs: [{ + input: this.currentCandidate, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.updateProgram, + output: this.currentCandidate, + inputs: [{ + input: this.currentCandidateCopy, + name: 'c' + }, { + input: this.previousCandidate, + name: 'ctm1' + }, { + input: this.currentInputGateState, + name: 'i' + }, { + input: this.currentForgetGateState, + name: 'f' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousCandidate, + inputs: [{ + input: this.currentCandidate, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.currentCandidatePreactiv, + inputs: [{ + input: this.currentCandidate, + name: 'source' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.currentCandidate, + inputs: [{ + input: this.currentCandidatePreactiv, + name: 'x' + }] + }); + } else { + this.currentCandidate = this.currentCandidatePreactiv; + } + + _WebGL.webgl2.runProgram({ + program: this.gateProductProgram, + output: this.currentHiddenState, + inputs: [{ + input: this.currentOutputGateState, + name: 't1' + }, { + input: this.currentCandidate, + name: 't2' + }] + }); + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const dimInputGate = this.weights['b_i'].glTextureShape[1]; + const dimCandidate = this.weights['b_c'].glTextureShape[1]; + const dimForgetGate = this.weights['b_f'].glTextureShape[1]; + const dimOutputGate = this.weights['b_o'].glTextureShape[1]; + + if (!this.currentInputGateState) { + this.currentInputGateState = new _Tensor.default([], [dimInputGate]); + this.currentInputGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentInputGateStatePreactiv) { + this.currentInputGateStatePreactiv = new _Tensor.default([], [dimInputGate]); + this.currentInputGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXI) { + this.tempXI = new _Tensor.default([], [dimInputGate]); + this.tempXI.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHI) { + this.tempHI = new _Tensor.default([], [dimInputGate]); + this.tempHI.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentForgetGateState) { + this.currentForgetGateState = new _Tensor.default([], [dimForgetGate]); + this.currentForgetGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentForgetGateStatePreactiv) { + this.currentForgetGateStatePreactiv = new _Tensor.default([], [dimForgetGate]); + this.currentForgetGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXF) { + this.tempXF = new _Tensor.default([], [dimForgetGate]); + this.tempXF.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHF) { + this.tempHF = new _Tensor.default([], [dimForgetGate]); + this.tempHF.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentOutputGateState) { + this.currentOutputGateState = new _Tensor.default([], [dimOutputGate]); + this.currentOutputGateState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentOutputGateStatePreactiv) { + this.currentOutputGateStatePreactiv = new _Tensor.default([], [dimOutputGate]); + this.currentOutputGateStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXO) { + this.tempXO = new _Tensor.default([], [dimOutputGate]); + this.tempXO.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHO) { + this.tempHO = new _Tensor.default([], [dimOutputGate]); + this.tempHO.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentCandidate) { + this.currentCandidate = new _Tensor.default([], [dimCandidate]); + this.currentCandidate.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentCandidateCopy) { + this.currentCandidateCopy = new _Tensor.default([], [dimCandidate]); + this.currentCandidateCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentCandidatePreactiv) { + this.currentCandidatePreactiv = new _Tensor.default([], [dimCandidate]); + this.currentCandidatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXC) { + this.tempXC = new _Tensor.default([], [dimCandidate]); + this.tempXC.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHC) { + this.tempHC = new _Tensor.default([], [dimCandidate]); + this.tempHC.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.previousCandidate || !this.stateful) { + this.previousCandidate = new _Tensor.default([], [dimCandidate]); + this.previousCandidate.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new _Tensor.default([], [dimCandidate]); + this.currentHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.previousHiddenState) { + this.previousHiddenState = new _Tensor.default([], [dimCandidate]); + this.previousHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new _Tensor.default([], [x.glTextureShape[0], dimCandidate]); + this.hiddenStateSequence.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new _Tensor.default([], [x.glTextureShape[0], dimCandidate]); + this.hiddenStateSequenceCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentX) { + this.currentX = new _Tensor.default([], [x.glTextureShape[1]]); + this.currentX.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _WebGL.webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: inputIndex, + type: 'int', + name: 'index' + }] + }); + + this._stepGPU(); + + if (this.returnSequences) { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ + input: this.hiddenStateSequence, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ + input: this.currentHiddenState, + name: 'x' + }, { + input: this.hiddenStateSequenceCopy, + name: 'y' + }], + uniforms: [{ + value: i, + type: 'int', + name: 'index' + }] + }); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = this.currentHiddenState; + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = LSTM; \ No newline at end of file diff --git a/lib/layers/recurrent/SimpleRNN.js b/lib/layers/recurrent/SimpleRNN.js new file mode 100644 index 0000000000..d8f3060b6e --- /dev/null +++ b/lib/layers/recurrent/SimpleRNN.js @@ -0,0 +1,355 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var activations = _interopRequireWildcard(require("../../activations")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _cwise = _interopRequireDefault(require("cwise")); + +var activationProgramSources = _interopRequireWildcard(require("../../activations/programSources")); + +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; } } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; +const gateSummationProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D t1;\r\nuniform sampler2D t2;\r\nuniform sampler2D bias;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(bias, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float t1_val = texelFetch(t1, ivec2(out_x, out_y), 0).r;\r\n float t2_val = texelFetch(t2, ivec2(out_x, out_y), 0).r;\r\n float bias_val = texelFetch(bias, ivec2(out_x, out_y), 0).r;\r\n\r\n outColor = vec4(t1_val + t2_val + bias_val);\r\n}\r\n"; +const timestepReadProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n\r\n outColor = vec4(texelFetch(x, ivec2(out_x, index), 0).r);\r\n}\r\n"; +const timestepWriteProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform sampler2D y;\r\nuniform int index;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(y, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (out_y == index) {\r\n outColor = vec4(texelFetch(x, ivec2(out_x, 0), 0).r);\r\n } else {\r\n outColor = vec4(texelFetch(y, ivec2(out_x, out_y), 0).r);\r\n }\r\n}\r\n"; + +class SimpleRNN extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + Object.defineProperty(this, "_combine", { + configurable: true, + enumerable: true, + writable: true, + value: (0, _cwise.default)({ + args: ['array', 'array', 'array', 'array'], + body: function (_y, _x1, _x2, _b) { + _y = _x1 + _x2 + _b; + } + }) + }); + this.layerClass = 'SimpleRNN'; + const { + units = 1, + activation = 'tanh', + use_bias = true, + return_sequences = false, + go_backwards = false, + stateful = false + } = attrs; + this.units = units; + this.activation = activation; + this.activationFunc = activations[activation]; + this.use_bias = use_bias; + this.returnSequences = return_sequences; + this.goBackwards = go_backwards; + this.stateful = stateful; + this.params = this.use_bias ? ['kernel', 'recurrent_kernel', 'bias'] : ['kernel', 'recurrent_kernel']; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + this.matMulProgram = _WebGL.webgl2.compileProgram(matMulProgramSource); + this.activationProgram = _WebGL.webgl2.compileProgram(activationProgramSources[this.activation]); + this.gateSummationProgram = _WebGL.webgl2.compileProgram(gateSummationProgramSource); + this.timestepReadProgram = _WebGL.webgl2.compileProgram(timestepReadProgramSource); + this.timestepWriteProgram = _WebGL.webgl2.compileProgram(timestepWriteProgramSource); + } + } + + setWeights(weightsArr) { + super.setWeights(weightsArr); + + if (!this.use_bias) { + this.weights['bias'] = new _Tensor.default([], [this.units]); + + if (this.gpu) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const dimHiddenState = this.units; + const currentHiddenState = this.stateful && this.currentHiddenState ? this.currentHiddenState : new _Tensor.default([], [dimHiddenState]); + const tempXH = new _Tensor.default([], [dimHiddenState]); + const tempHH = new _Tensor.default([], [dimHiddenState]); + const previousHiddenState = new _Tensor.default([], [dimHiddenState]); + this.hiddenStateSequence = new _Tensor.default([], [x.tensor.shape[0], dimHiddenState]); + const currentX = new _Tensor.default([], [x.tensor.shape[1]]); + + const _step = () => { + _ndarrayOps.default.assign(previousHiddenState.tensor, currentHiddenState.tensor); + + (0, _ndarrayBlasLevel.gemv)(1, this.weights['kernel'].tensor.transpose(1, 0), currentX.tensor, 1, tempXH.tensor); + (0, _ndarrayBlasLevel.gemv)(1, this.weights['recurrent_kernel'].tensor.transpose(1, 0), previousHiddenState.tensor, 1, tempHH.tensor); + + this._combine(currentHiddenState.tensor, tempXH.tensor, tempHH.tensor, this.weights['bias'].tensor); + + this.activationFunc(currentHiddenState); + }; + + for (let i = 0, len = x.tensor.shape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _ndarrayOps.default.assign(currentX.tensor, x.tensor.pick(inputIndex, null)); + + const tempTensors = [tempXH, tempHH]; + tempTensors.forEach(temp => _ndarrayOps.default.assigns(temp.tensor, 0)); + + _step(); + + if (this.returnSequences) { + _ndarrayOps.default.assign(this.hiddenStateSequence.tensor.pick(i, null), currentHiddenState.tensor); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = currentHiddenState; + } + + if (this.stateful) { + this.currentHiddenState = currentHiddenState; + } + } + + _stepGPU() { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.previousHiddenState, + inputs: [{ + input: this.currentHiddenState, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempXH, + inputs: [{ + input: this.currentX, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.matMulProgram, + output: this.tempHH, + inputs: [{ + input: this.previousHiddenState, + name: 'A' + }, { + input: this.weights['recurrent_kernel'], + name: 'B' + }], + uniforms: [{ + value: 0, + type: 'bool', + name: 'addC' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.gateSummationProgram, + output: this.currentHiddenStatePreactiv, + inputs: [{ + input: this.tempXH, + name: 't1' + }, { + input: this.tempHH, + name: 't2' + }, { + input: this.weights['bias'], + name: 'bias' + }] + }); + + if (this.activation !== 'linear') { + _WebGL.webgl2.runProgram({ + program: this.activationProgram, + output: this.currentHiddenState, + inputs: [{ + input: this.currentHiddenStatePreactiv, + name: 'x' + }] + }); + } else { + this.currentHiddenState = this.currentHiddenStatePreactiv; + } + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const dimHiddenState = this.units; + + if (!this.currentHiddenState || !this.stateful) { + this.currentHiddenState = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentHiddenStatePreactiv) { + this.currentHiddenStatePreactiv = new _Tensor.default([], [dimHiddenState]); + this.currentHiddenStatePreactiv.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempXH) { + this.tempXH = new _Tensor.default([], [dimHiddenState]); + this.tempXH.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.tempHH) { + this.tempHH = new _Tensor.default([], [dimHiddenState]); + this.tempHH.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.previousHiddenState) { + this.previousHiddenState = new _Tensor.default([], [dimHiddenState]); + this.previousHiddenState.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequence) { + this.hiddenStateSequence = new _Tensor.default([], [x.glTextureShape[0], dimHiddenState]); + this.hiddenStateSequence.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.hiddenStateSequenceCopy) { + this.hiddenStateSequenceCopy = new _Tensor.default([], [x.glTextureShape[0], dimHiddenState]); + this.hiddenStateSequenceCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.currentX) { + this.currentX = new _Tensor.default([], [x.glTextureShape[1]]); + this.currentX.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + for (let i = 0, len = x.glTextureShape[0]; i < len; i++) { + const inputIndex = this.goBackwards ? len - i - 1 : i; + + _WebGL.webgl2.runProgram({ + program: this.timestepReadProgram, + output: this.currentX, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: inputIndex, + type: 'int', + name: 'index' + }] + }); + + this._stepGPU(); + + if (this.returnSequences) { + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.hiddenStateSequenceCopy, + inputs: [{ + input: this.hiddenStateSequence, + name: 'source' + }] + }); + + _WebGL.webgl2.runProgram({ + program: this.timestepWriteProgram, + output: this.hiddenStateSequence, + inputs: [{ + input: this.currentHiddenState, + name: 'x' + }, { + input: this.hiddenStateSequenceCopy, + name: 'y' + }], + uniforms: [{ + value: i, + type: 'int', + name: 'index' + }] + }); + } + } + + if (this.returnSequences) { + this.output = this.hiddenStateSequence; + } else { + this.output = this.currentHiddenState; + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = SimpleRNN; \ No newline at end of file diff --git a/lib/layers/recurrent/index.js b/lib/layers/recurrent/index.js new file mode 100644 index 0000000000..d5f72ef7fb --- /dev/null +++ b/lib/layers/recurrent/index.js @@ -0,0 +1,31 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "SimpleRNN", { + enumerable: true, + get: function () { + return _SimpleRNN.default; + } +}); +Object.defineProperty(exports, "LSTM", { + enumerable: true, + get: function () { + return _LSTM.default; + } +}); +Object.defineProperty(exports, "GRU", { + enumerable: true, + get: function () { + return _GRU.default; + } +}); + +var _SimpleRNN = _interopRequireDefault(require("./SimpleRNN")); + +var _LSTM = _interopRequireDefault(require("./LSTM")); + +var _GRU = _interopRequireDefault(require("./GRU")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/layers/wrappers/Bidirectional.js b/lib/layers/wrappers/Bidirectional.js new file mode 100644 index 0000000000..736ca2e452 --- /dev/null +++ b/lib/layers/wrappers/Bidirectional.js @@ -0,0 +1,210 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var recurrentLayers = _interopRequireWildcard(require("../recurrent")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const concatMergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D forward;\r\nuniform sampler2D backward;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(forward, 0);\r\n int out_x = int(float(size[0] * 2) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (out_x >= 0 && out_x < size[0]) {\r\n outColor = vec4(texelFetch(forward, ivec2(out_x, out_y), 0).r);\r\n } else {\r\n outColor = vec4(texelFetch(backward, ivec2(out_x - size[0], size[1] - out_y - 1), 0).r);\r\n }\r\n}\r\n"; +const sumMergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D forward;\r\nuniform sampler2D backward;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(forward, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r;\r\n float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r;\r\n\r\n outColor = vec4(forward_val + backward_val);\r\n}\r\n"; +const mulMergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D forward;\r\nuniform sampler2D backward;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(forward, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r;\r\n float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r;\r\n\r\n outColor = vec4(forward_val * backward_val);\r\n}\r\n"; +const aveMergeProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D forward;\r\nuniform sampler2D backward;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(forward, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float forward_val = texelFetch(forward, ivec2(out_x, out_y), 0).r;\r\n float backward_val = texelFetch(backward, ivec2(out_x, size[1] - out_y - 1), 0).r;\r\n\r\n outColor = vec4(0.5 * (forward_val + backward_val));\r\n}\r\n"; + +class Bidirectional extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'Bidirectional'; + const { + layer, + merge_mode = 'concat' + } = attrs; + + if (!layer) { + this.throwError('wrapped layer is undefined.'); + } + + if (!['SimpleRNN', 'GRU', 'LSTM'].includes(layer.class_name)) { + this.throwError(`cannot wrap ${layer.class_name} layer.`); + } + + if (!['concat', 'sum', 'mul', 'ave'].includes(merge_mode)) { + this.throwError(`merge_mode ${merge_mode} not supported.`); + } + + const forwardLayerAttrs = Object.assign({}, layer.config, { + gpu: attrs.gpu + }); + const backwardLayerAttrs = Object.assign({}, layer.config, { + gpu: attrs.gpu + }); + backwardLayerAttrs.go_backwards = !backwardLayerAttrs.go_backwards; + this.forwardLayer = new recurrentLayers[layer.class_name](forwardLayerAttrs); + this.backwardLayer = new recurrentLayers[layer.class_name](backwardLayerAttrs); + this.forwardLayer.outbound = [null]; + this.backwardLayer.outbound = [null]; + this.mergeMode = merge_mode; + this.returnSequences = layer.config.return_sequences; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + + if (this.mergeMode === 'concat') { + this.mergeProgram = _WebGL.webgl2.compileProgram(concatMergeProgramSource); + } else if (this.mergeMode === 'sum') { + this.mergeProgram = _WebGL.webgl2.compileProgram(sumMergeProgramSource); + } else if (this.mergeMode === 'mul') { + this.mergeProgram = _WebGL.webgl2.compileProgram(mulMergeProgramSource); + } else if (this.mergeMode === 'ave') { + this.mergeProgram = _WebGL.webgl2.compileProgram(aveMergeProgramSource); + } + } + } + + setWeights(weightsArr) { + this.forwardLayer.setWeights(weightsArr.slice(0, weightsArr.length / 2)); + this.backwardLayer.setWeights(weightsArr.slice(weightsArr.length / 2)); + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + this.forwardLayer._callCPU(new _Tensor.default(x.tensor.data, x.tensor.shape)); + + this.backwardLayer._callCPU(new _Tensor.default(x.tensor.data, x.tensor.shape)); + + const forwardOutput = this.forwardLayer.output; + const backwardOutput = this.backwardLayer.output; + + if (this.returnSequences) { + backwardOutput.tensor = backwardOutput.tensor.step(-1); + } + + const outShape = forwardOutput.tensor.shape.slice(); + + if (this.mergeMode === 'concat') { + outShape[outShape.length - 1] += backwardOutput.tensor.shape[outShape.length - 1]; + } + + this.output = new _Tensor.default([], outShape); + + if (this.mergeMode === 'concat') { + if (this.returnSequences) { + _ndarrayOps.default.assign(this.output.tensor.hi(outShape[0], forwardOutput.tensor.shape[1]).lo(0, 0), forwardOutput.tensor); + + _ndarrayOps.default.assign(this.output.tensor.hi(outShape[0], outShape[1]).lo(0, forwardOutput.tensor.shape[1]), backwardOutput.tensor); + } else { + _ndarrayOps.default.assign(this.output.tensor.hi(forwardOutput.tensor.shape[0]).lo(0), forwardOutput.tensor); + + _ndarrayOps.default.assign(this.output.tensor.hi(outShape[0]).lo(forwardOutput.tensor.shape[0]), backwardOutput.tensor); + } + } else if (this.mergeMode === 'sum') { + _ndarrayOps.default.addeq(this.output.tensor, forwardOutput.tensor); + + _ndarrayOps.default.addeq(this.output.tensor, backwardOutput.tensor); + } else if (this.mergeMode === 'mul') { + _ndarrayOps.default.assigns(this.output.tensor, 1); + + _ndarrayOps.default.muleq(this.output.tensor, forwardOutput.tensor); + + _ndarrayOps.default.muleq(this.output.tensor, backwardOutput.tensor); + } else if (this.mergeMode === 'ave') { + _ndarrayOps.default.addeq(this.output.tensor, forwardOutput.tensor); + + _ndarrayOps.default.addeq(this.output.tensor, backwardOutput.tensor); + + _ndarrayOps.default.divseq(this.output.tensor, 2); + } + } + + _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.inputCopy) { + this.inputCopy = new _Tensor.default([], x.glTextureShape); + this.inputCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.inputCopy, + inputs: [{ + input: x, + name: 'source' + }] + }); + + this.forwardLayer._callGPU(x); + + this.backwardLayer._callGPU(this.inputCopy); + + const forwardOutput = this.forwardLayer.output; + const backwardOutput = this.backwardLayer.output; + const outShape = forwardOutput.glTextureShape.slice(); + + if (this.mergeMode === 'concat') { + outShape[1] += backwardOutput.glTextureShape[1]; + } + + if (!this.output) { + this.output = new _Tensor.default([], outShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + + if (!this.returnSequences) { + this.output.is1D = true; + } + } + + _WebGL.webgl2.runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: [{ + input: forwardOutput, + name: 'forward' + }, { + input: backwardOutput, + name: 'backward' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + +} + +exports.default = Bidirectional; \ No newline at end of file diff --git a/lib/layers/wrappers/TimeDistributed.js b/lib/layers/wrappers/TimeDistributed.js new file mode 100644 index 0000000000..842ffa9993 --- /dev/null +++ b/lib/layers/wrappers/TimeDistributed.js @@ -0,0 +1,409 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Layer = _interopRequireDefault(require("../../Layer")); + +var _Tensor = _interopRequireDefault(require("../../Tensor")); + +var _WebGL = require("../../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var layers = _interopRequireWildcard(require("../")); + +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; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const copyTextureProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D source;\r\nout vec4 outColor;\r\n\r\nvoid main(void) {\r\n outColor = texture(source, vec2(outTex.x, outTex.y));\r\n}\r\n"; +const mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +const selectSliceProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int t;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n\r\n outColor = vec4(texelFetch(x, ivec2(out_x, t), 0).r);\r\n}\r\n"; +const copySliceOutputProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D outputCopy;\r\nuniform sampler2D sliceOutput;\r\nuniform int t;\r\nuniform int timesteps;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(sliceOutput, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(timesteps) * outTex.y);\r\n\r\n if (t == out_y) {\r\n outColor = vec4(texelFetch(sliceOutput, ivec2(out_x, 0), 0).r);\r\n } else {\r\n outColor = texelFetch(outputCopy, ivec2(out_x, out_y), 0);\r\n }\r\n}\r\n"; +const mapSliceOutputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D outputCopy;\r\nuniform sampler2D sliceOutput;\r\nuniform isampler2D indexMap;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(outputCopy, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(textureSize(sliceOutput, 0)[0])));\r\n int colIndex = int(mod(float(index), float(textureSize(sliceOutput, 0)[0])));\r\n float val = texelFetch(sliceOutput, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = texelFetch(outputCopy, ivec2(out_x, out_y), 0);\r\n }\r\n}\r\n"; + +class TimeDistributed extends _Layer.default { + constructor(attrs = {}) { + super(attrs); + this.layerClass = 'TimeDistributed'; + const { + layer + } = attrs; + + if (!layer) { + this.throwError('wrapped layer is undefined.'); + } + + const wrappedLayerAttrs = Object.assign({}, layer.config, { + gpu: attrs.gpu + }); + this.wrappedLayer = new layers[layer.class_name](wrappedLayerAttrs); + this.wrappedLayer.outbound = [null]; + + if (this.gpu) { + this.copyTextureProgram = _WebGL.webgl2.compileProgram(copyTextureProgramSource); + this.mapInputProgram = _WebGL.webgl2.compileProgram(mapInputProgramSource); + this.selectSliceProgram = _WebGL.webgl2.compileProgram(selectSliceProgramSource); + this.copySliceOutputProgram = _WebGL.webgl2.compileProgram(copySliceOutputProgramSource); + this.mapSliceOutputProgram = _WebGL.webgl2.compileProgram(mapSliceOutputProgramSource); + } + } + + setWeights(weightsArr) { + this.wrappedLayer.setWeights(weightsArr); + } + + call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + + _callCPU(x) { + const stepShape = [...x.tensor.shape.slice(1)]; + const step = new _Tensor.default([], stepShape); + + _ndarrayOps.default.assign(step.tensor, x.tensor.pick(0, ...Array(stepShape.length).fill(null))); + + let stepOutput = this.wrappedLayer.call(step); + const stepOutputShape = stepOutput.tensor.shape.slice(); + this.output = new _Tensor.default([], [x.tensor.shape[0], ...stepOutputShape]); + + _ndarrayOps.default.assign(this.output.tensor.pick(0, ...Array(stepOutputShape.length).fill(null)), stepOutput.tensor); + + for (let i = 1, timesteps = x.tensor.shape[0]; i < timesteps; i++) { + _ndarrayOps.default.assign(step.tensor, x.tensor.pick(i, ...Array(stepShape.length).fill(null))); + + stepOutput = this.wrappedLayer.call(step); + + _ndarrayOps.default.assign(this.output.tensor.pick(i, ...Array(stepOutputShape.length).fill(null)), stepOutput.tensor); + } + } + + _createIndexMap(indicesForReshaped) { + if (this.indexMaps) { + return; + } + + const indices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.indexMaps = []; + const timesteps = this.inputShape[0]; + const sliceShape = this.inputShape.slice(1); + + for (let t = 0; t < timesteps; t++) { + const sliceIndices = new _Tensor.default([], sliceShape, { + type: Int32Array + }); + + _ndarrayOps.default.assign(sliceIndices.tensor, indices.tensor.pick(t, ...Array(sliceShape.length).fill(null))); + + sliceIndices.reshapeTo2DSquare(); + sliceIndices.createGLTexture({ + type: '2d', + format: 'int' + }); + this.indexMaps.push(sliceIndices); + } + } + + _createOutputIndexMap(indicesForReshaped) { + if (this.outputIndexMaps) { + return; + } + + const outputSliceIndices = new _Tensor.default(indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + this.outputIndexMaps = []; + const timesteps = this.outputShape[0]; + const sliceShape = this.outputShape.slice(1); + + for (let t = 0; t < timesteps; t++) { + const outputIndices = new _Tensor.default([], this.outputShape, { + type: Int32Array + }); + + _ndarrayOps.default.assigns(outputIndices.tensor, -1); + + _ndarrayOps.default.assign(outputIndices.tensor.pick(t, ...Array(sliceShape.length).fill(null)), outputSliceIndices.tensor); + + outputIndices.reshapeTo2DSquare(); + outputIndices.createGLTexture({ + type: '2d', + format: 'int' + }); + this.outputIndexMaps.push(outputIndices); + } + } + + _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + this.inputShape = x.tensor.shape; + } + + if (!x.glTexture) { + if (x.tensor.shape.length <= 2) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } else if (x.tensor.shape.length > 2 && !x.is2DReshaped) { + x.reshapeTo2DSquare(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + + if (this.inputShape.length > 2) { + this._createIndexMap(x.indicesForReshaped); + } + + const timesteps = this.inputShape[0]; + const sliceShape = this.inputShape.slice(1); + + if (!this.slice) { + this.slice = new _Tensor.default([], sliceShape); + + if (sliceShape.length <= 2) { + this.slice.createGLTexture({ + type: '2d', + format: 'float' + }); + } else { + this.slice.reshapeTo2DSquare(); + this.slice.createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + + if (this.inputShape.length <= 2) { + _WebGL.webgl2.runProgram({ + program: this.selectSliceProgram, + output: this.slice, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: 0, + type: 'int', + name: 't' + }] + }); + } else { + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.slice, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMaps[0], + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + } + + this.wrappedLayer._callGPU(this.slice); + + this.sliceOutput = this.wrappedLayer.output; + + if (!this.output) { + if (this.inputShape.length <= 2) { + this.outputShape = [timesteps, this.sliceOutput.glTextureShape[1]]; + this.output = new _Tensor.default([], this.outputShape); + this.outputCopy = new _Tensor.default([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + this.outputCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + } else { + this.outputShape = [timesteps, ...this.sliceOutput.originalShape]; + this.output = new _Tensor.default([], this.outputShape); + this.outputCopy = new _Tensor.default([], this.outputShape); + this.output.reshapeTo2DSquare(); + this.outputCopy.reshapeTo2DSquare(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + this.outputCopy.createGLTexture({ + type: '2d', + format: 'float' + }); + + this._createOutputIndexMap(this.sliceOutput.indicesForReshaped); + } + } + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.outputCopy, + inputs: [{ + input: this.output, + name: 'source' + }] + }); + + if (this.inputShape.length <= 2) { + _WebGL.webgl2.runProgram({ + program: this.copySliceOutputProgram, + output: this.output, + inputs: [{ + input: this.outputCopy, + name: 'outputCopy' + }, { + input: this.sliceOutput, + name: 'sliceOutput' + }], + uniforms: [{ + value: 0, + type: 'int', + name: 't' + }, { + value: timesteps, + type: 'int', + name: 'timesteps' + }] + }); + } else { + _WebGL.webgl2.runProgram({ + program: this.mapSliceOutputProgram, + output: this.output, + inputs: [{ + input: this.outputCopy, + name: 'outputCopy' + }, { + input: this.sliceOutput, + name: 'sliceOutput' + }, { + input: this.outputIndexMaps[0], + name: 'indexMap' + }] + }); + } + + for (let i = 1; i < timesteps; i++) { + if (this.inputShape.length <= 2) { + _WebGL.webgl2.runProgram({ + program: this.selectSliceProgram, + output: this.slice, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: i, + type: 'int', + name: 't' + }] + }); + } else { + _WebGL.webgl2.runProgram({ + program: this.mapInputProgram, + output: this.slice, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMaps[i], + name: 'indexMap' + }], + uniforms: [{ + value: x.glTextureShape[1], + type: 'int', + name: 'inputCols' + }] + }); + } + + this.wrappedLayer._callGPU(this.slice); + + this.sliceOutput = this.wrappedLayer.output; + + _WebGL.webgl2.runProgram({ + program: this.copyTextureProgram, + output: this.outputCopy, + inputs: [{ + input: this.output, + name: 'source' + }] + }); + + if (this.inputShape.length <= 2) { + _WebGL.webgl2.runProgram({ + program: this.copySliceOutputProgram, + output: this.output, + inputs: [{ + input: this.outputCopy, + name: 'outputCopy' + }, { + input: this.sliceOutput, + name: 'sliceOutput' + }], + uniforms: [{ + value: i, + type: 'int', + name: 't' + }, { + value: timesteps, + type: 'int', + name: 'timesteps' + }] + }); + } else { + _WebGL.webgl2.runProgram({ + program: this.mapSliceOutputProgram, + output: this.output, + inputs: [{ + input: this.outputCopy, + name: 'outputCopy' + }, { + input: this.sliceOutput, + name: 'sliceOutput' + }, { + input: this.outputIndexMaps[i], + name: 'indexMap' + }] + }); + } + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + +} + +exports.default = TimeDistributed; \ No newline at end of file diff --git a/lib/layers/wrappers/index.js b/lib/layers/wrappers/index.js new file mode 100644 index 0000000000..48c31cf75e --- /dev/null +++ b/lib/layers/wrappers/index.js @@ -0,0 +1,23 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "TimeDistributed", { + enumerable: true, + get: function () { + return _TimeDistributed.default; + } +}); +Object.defineProperty(exports, "Bidirectional", { + enumerable: true, + get: function () { + return _Bidirectional.default; + } +}); + +var _TimeDistributed = _interopRequireDefault(require("./TimeDistributed")); + +var _Bidirectional = _interopRequireDefault(require("./Bidirectional")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/local-path.js b/lib/local-path.js deleted file mode 100644 index 6bcceb05b0..0000000000 --- a/lib/local-path.js +++ /dev/null @@ -1,13 +0,0 @@ -const path = require('path') - -module.exports = { - isLocalPath (templatePath) { - return /^[./]|(^[a-zA-Z]:)/.test(templatePath) - }, - - getTemplatePath (templatePath) { - return path.isAbsolute(templatePath) - ? templatePath - : path.normalize(path.join(process.cwd(), templatePath)) - } -} diff --git a/lib/logger.js b/lib/logger.js deleted file mode 100644 index 31969d4251..0000000000 --- a/lib/logger.js +++ /dev/null @@ -1,44 +0,0 @@ -const chalk = require('chalk') -const format = require('util').format - -/** - * Prefix. - */ - -const prefix = ' vue-cli' -const sep = chalk.gray('·') - -/** - * Log a `message` to the console. - * - * @param {String} message - */ - -exports.log = function (...args) { - const msg = format.apply(format, args) - console.log(chalk.white(prefix), sep, msg) -} - -/** - * Log an error `message` to the console and exit. - * - * @param {String} message - */ - -exports.fatal = function (...args) { - if (args[0] instanceof Error) args[0] = args[0].message.trim() - const msg = format.apply(format, args) - console.error(chalk.red(prefix), sep, msg) - process.exit(1) -} - -/** - * Log a success `message` to the console and exit. - * - * @param {String} message - */ - -exports.success = function (...args) { - const msg = format.apply(format, args) - console.log(chalk.white(prefix), sep, msg) -} diff --git a/lib/options.js b/lib/options.js deleted file mode 100644 index a165366740..0000000000 --- a/lib/options.js +++ /dev/null @@ -1,89 +0,0 @@ -const path = require('path') -const metadata = require('read-metadata') -const exists = require('fs').existsSync -const getGitUser = require('./git-user') -const validateName = require('validate-npm-package-name') - -/** - * Read prompts metadata. - * - * @param {String} dir - * @return {Object} - */ - -module.exports = function options (name, dir) { - const opts = getMetadata(dir) - - setDefault(opts, 'name', name) - setValidateName(opts) - - const author = getGitUser() - if (author) { - setDefault(opts, 'author', author) - } - - return opts -} - -/** - * Gets the metadata from either a meta.json or meta.js file. - * - * @param {String} dir - * @return {Object} - */ - -function getMetadata (dir) { - const json = path.join(dir, 'meta.json') - const js = path.join(dir, 'meta.js') - let opts = {} - - if (exists(json)) { - opts = metadata.sync(json) - } else if (exists(js)) { - const req = require(path.resolve(js)) - if (req !== Object(req)) { - throw new Error('meta.js needs to expose an object') - } - opts = req - } - - return opts -} - -/** - * Set the default value for a prompt question - * - * @param {Object} opts - * @param {String} key - * @param {String} val - */ - -function setDefault (opts, key, val) { - if (opts.schema) { - opts.prompts = opts.schema - delete opts.schema - } - const prompts = opts.prompts || (opts.prompts = {}) - if (!prompts[key] || typeof prompts[key] !== 'object') { - prompts[key] = { - 'type': 'string', - 'default': val - } - } else { - prompts[key]['default'] = val - } -} - -function setValidateName (opts) { - const name = opts.prompts.name - const customValidate = name.validate - name.validate = name => { - const its = validateName(name) - if (!its.validForNewPackages) { - const errors = (its.errors || []).concat(its.warnings || []) - return 'Sorry, ' + errors.join(' and ') + '.' - } - if (typeof customValidate === 'function') return customValidate(name) - return true - } -} diff --git a/lib/proto.js b/lib/proto.js new file mode 100644 index 0000000000..7ea63640c3 --- /dev/null +++ b/lib/proto.js @@ -0,0 +1,352 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.Model = exports.Weights = void 0; + +var $protobuf = _interopRequireWildcard(require("protobufjs/minimal")); + +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; } } + +const $Reader = $protobuf.Reader, + $Writer = $protobuf.Writer, + $util = $protobuf.util; +const $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); +exports.default = $root; + +const Weights = $root.Weights = (() => { + function Weights(properties) { + this.shape = []; + if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + Weights.prototype.layerName = ""; + Weights.prototype.weightName = ""; + Weights.prototype.shape = $util.emptyArray; + Weights.prototype.type = ""; + Weights.prototype.data = $util.newBuffer([]); + Weights.prototype.quantizeMin = 0; + Weights.prototype.quantizeMax = 0; + + Weights.create = function create(properties) { + return new Weights(properties); + }; + + Weights.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.layerName != null && message.hasOwnProperty("layerName")) writer.uint32(10).string(message.layerName); + if (message.weightName != null && message.hasOwnProperty("weightName")) writer.uint32(18).string(message.weightName); + + if (message.shape != null && message.shape.length) { + writer.uint32(26).fork(); + + for (let i = 0; i < message.shape.length; ++i) writer.uint32(message.shape[i]); + + writer.ldelim(); + } + + if (message.type != null && message.hasOwnProperty("type")) writer.uint32(34).string(message.type); + if (message.data != null && message.hasOwnProperty("data")) writer.uint32(42).bytes(message.data); + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) writer.uint32(53).float(message.quantizeMin); + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) writer.uint32(61).float(message.quantizeMax); + return writer; + }; + + Weights.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + Weights.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.Weights(); + + while (reader.pos < end) { + let tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.layerName = reader.string(); + break; + + case 2: + message.weightName = reader.string(); + break; + + case 3: + if (!(message.shape && message.shape.length)) message.shape = []; + + if ((tag & 7) === 2) { + let end2 = reader.uint32() + reader.pos; + + while (reader.pos < end2) message.shape.push(reader.uint32()); + } else message.shape.push(reader.uint32()); + + break; + + case 4: + message.type = reader.string(); + break; + + case 5: + message.data = reader.bytes(); + break; + + case 6: + message.quantizeMin = reader.float(); + break; + + case 7: + message.quantizeMax = reader.float(); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }; + + Weights.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + Weights.verify = function verify(message) { + if (typeof message !== "object" || message === null) return "object expected"; + if (message.layerName != null && message.hasOwnProperty("layerName")) if (!$util.isString(message.layerName)) return "layerName: string expected"; + if (message.weightName != null && message.hasOwnProperty("weightName")) if (!$util.isString(message.weightName)) return "weightName: string expected"; + + if (message.shape != null && message.hasOwnProperty("shape")) { + if (!Array.isArray(message.shape)) return "shape: array expected"; + + for (let i = 0; i < message.shape.length; ++i) if (!$util.isInteger(message.shape[i])) return "shape: integer[] expected"; + } + + if (message.type != null && message.hasOwnProperty("type")) if (!$util.isString(message.type)) return "type: string expected"; + if (message.data != null && message.hasOwnProperty("data")) if (!(message.data && typeof message.data.length === "number" || $util.isString(message.data))) return "data: buffer expected"; + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) if (typeof message.quantizeMin !== "number") return "quantizeMin: number expected"; + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) if (typeof message.quantizeMax !== "number") return "quantizeMax: number expected"; + return null; + }; + + Weights.fromObject = function fromObject(object) { + if (object instanceof $root.Weights) return object; + let message = new $root.Weights(); + if (object.layerName != null) message.layerName = String(object.layerName); + if (object.weightName != null) message.weightName = String(object.weightName); + + if (object.shape) { + if (!Array.isArray(object.shape)) throw TypeError(".Weights.shape: array expected"); + message.shape = []; + + for (let i = 0; i < object.shape.length; ++i) message.shape[i] = object.shape[i] >>> 0; + } + + if (object.type != null) message.type = String(object.type); + if (object.data != null) if (typeof object.data === "string") $util.base64.decode(object.data, message.data = $util.newBuffer($util.base64.length(object.data)), 0);else if (object.data.length) message.data = object.data; + if (object.quantizeMin != null) message.quantizeMin = Number(object.quantizeMin); + if (object.quantizeMax != null) message.quantizeMax = Number(object.quantizeMax); + return message; + }; + + Weights.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.shape = []; + + if (options.defaults) { + object.layerName = ""; + object.weightName = ""; + object.type = ""; + object.data = options.bytes === String ? "" : []; + object.quantizeMin = 0; + object.quantizeMax = 0; + } + + if (message.layerName != null && message.hasOwnProperty("layerName")) object.layerName = message.layerName; + if (message.weightName != null && message.hasOwnProperty("weightName")) object.weightName = message.weightName; + + if (message.shape && message.shape.length) { + object.shape = []; + + for (let j = 0; j < message.shape.length; ++j) object.shape[j] = message.shape[j]; + } + + if (message.type != null && message.hasOwnProperty("type")) object.type = message.type; + if (message.data != null && message.hasOwnProperty("data")) object.data = options.bytes === String ? $util.base64.encode(message.data, 0, message.data.length) : options.bytes === Array ? Array.prototype.slice.call(message.data) : message.data; + if (message.quantizeMin != null && message.hasOwnProperty("quantizeMin")) object.quantizeMin = options.json && !isFinite(message.quantizeMin) ? String(message.quantizeMin) : message.quantizeMin; + if (message.quantizeMax != null && message.hasOwnProperty("quantizeMax")) object.quantizeMax = options.json && !isFinite(message.quantizeMax) ? String(message.quantizeMax) : message.quantizeMax; + return object; + }; + + Weights.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Weights; +})(); + +exports.Weights = Weights; + +const Model = $root.Model = (() => { + function Model(properties) { + this.modelWeights = []; + if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) this[keys[i]] = properties[keys[i]]; + } + + Model.prototype.id = ""; + Model.prototype.name = ""; + Model.prototype.kerasVersion = ""; + Model.prototype.backend = ""; + Model.prototype.modelConfig = ""; + Model.prototype.modelWeights = $util.emptyArray; + + Model.create = function create(properties) { + return new Model(properties); + }; + + Model.encode = function encode(message, writer) { + if (!writer) writer = $Writer.create(); + if (message.id != null && message.hasOwnProperty("id")) writer.uint32(10).string(message.id); + if (message.name != null && message.hasOwnProperty("name")) writer.uint32(18).string(message.name); + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) writer.uint32(26).string(message.kerasVersion); + if (message.backend != null && message.hasOwnProperty("backend")) writer.uint32(34).string(message.backend); + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) writer.uint32(42).string(message.modelConfig); + if (message.modelWeights != null && message.modelWeights.length) for (let i = 0; i < message.modelWeights.length; ++i) $root.Weights.encode(message.modelWeights[i], writer.uint32(50).fork()).ldelim(); + return writer; + }; + + Model.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + Model.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, + message = new $root.Model(); + + while (reader.pos < end) { + let tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.id = reader.string(); + break; + + case 2: + message.name = reader.string(); + break; + + case 3: + message.kerasVersion = reader.string(); + break; + + case 4: + message.backend = reader.string(); + break; + + case 5: + message.modelConfig = reader.string(); + break; + + case 6: + if (!(message.modelWeights && message.modelWeights.length)) message.modelWeights = []; + message.modelWeights.push($root.Weights.decode(reader, reader.uint32())); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }; + + Model.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + Model.verify = function verify(message) { + if (typeof message !== "object" || message === null) return "object expected"; + if (message.id != null && message.hasOwnProperty("id")) if (!$util.isString(message.id)) return "id: string expected"; + if (message.name != null && message.hasOwnProperty("name")) if (!$util.isString(message.name)) return "name: string expected"; + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) if (!$util.isString(message.kerasVersion)) return "kerasVersion: string expected"; + if (message.backend != null && message.hasOwnProperty("backend")) if (!$util.isString(message.backend)) return "backend: string expected"; + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) if (!$util.isString(message.modelConfig)) return "modelConfig: string expected"; + + if (message.modelWeights != null && message.hasOwnProperty("modelWeights")) { + if (!Array.isArray(message.modelWeights)) return "modelWeights: array expected"; + + for (let i = 0; i < message.modelWeights.length; ++i) { + let error = $root.Weights.verify(message.modelWeights[i]); + if (error) return "modelWeights." + error; + } + } + + return null; + }; + + Model.fromObject = function fromObject(object) { + if (object instanceof $root.Model) return object; + let message = new $root.Model(); + if (object.id != null) message.id = String(object.id); + if (object.name != null) message.name = String(object.name); + if (object.kerasVersion != null) message.kerasVersion = String(object.kerasVersion); + if (object.backend != null) message.backend = String(object.backend); + if (object.modelConfig != null) message.modelConfig = String(object.modelConfig); + + if (object.modelWeights) { + if (!Array.isArray(object.modelWeights)) throw TypeError(".Model.modelWeights: array expected"); + message.modelWeights = []; + + for (let i = 0; i < object.modelWeights.length; ++i) { + if (typeof object.modelWeights[i] !== "object") throw TypeError(".Model.modelWeights: object expected"); + message.modelWeights[i] = $root.Weights.fromObject(object.modelWeights[i]); + } + } + + return message; + }; + + Model.toObject = function toObject(message, options) { + if (!options) options = {}; + let object = {}; + if (options.arrays || options.defaults) object.modelWeights = []; + + if (options.defaults) { + object.id = ""; + object.name = ""; + object.kerasVersion = ""; + object.backend = ""; + object.modelConfig = ""; + } + + if (message.id != null && message.hasOwnProperty("id")) object.id = message.id; + if (message.name != null && message.hasOwnProperty("name")) object.name = message.name; + if (message.kerasVersion != null && message.hasOwnProperty("kerasVersion")) object.kerasVersion = message.kerasVersion; + if (message.backend != null && message.hasOwnProperty("backend")) object.backend = message.backend; + if (message.modelConfig != null && message.hasOwnProperty("modelConfig")) object.modelConfig = message.modelConfig; + + if (message.modelWeights && message.modelWeights.length) { + object.modelWeights = []; + + for (let j = 0; j < message.modelWeights.length; ++j) object.modelWeights[j] = $root.Weights.toObject(message.modelWeights[j], options); + } + + return object; + }; + + Model.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Model; +})(); + +exports.Model = Model; \ No newline at end of file diff --git a/lib/utils/tensorUtils.js b/lib/utils/tensorUtils.js new file mode 100644 index 0000000000..b2d81ffb1b --- /dev/null +++ b/lib/utils/tensorUtils.js @@ -0,0 +1,89 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.checkShape = checkShape; +exports.data3DLayoutForGL = data3DLayoutForGL; +exports.createIndicesFor2DReshaped = createIndicesFor2DReshaped; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +var _ndarray = _interopRequireDefault(require("ndarray")); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function checkShape(data, shape) { + if (data.length && shape.length && data.length !== shape.reduce((a, b) => a * b, 1)) { + throw new Error('[Tensor] specified shape incompatible with data.'); + } +} + +function data3DLayoutForGL(typedarrayConstructor, arr, shape) { + const data = new typedarrayConstructor(arr.data.length); + const slice = (0, _ndarray.default)(new typedarrayConstructor(shape[0] * shape[1]), [shape[0], shape[1]]); + let offset = 0; + + for (let i = 0; i < shape[2]; i++) { + _ndarrayOps.default.assign(slice, arr.pick(null, null, i)); + + data.set(slice.data, offset); + offset += shape[0] * shape[1]; + } + + return data; +} + +function createIndicesFor2DReshaped(shape, square = false, axis = -1) { + const size = shape.reduce((a, b) => a * b, 1); + const indicesArr = (0, _ndarray.default)(new Int32Array(size), shape); + + if (square) { + const squareDim = Math.ceil(Math.sqrt(size)); + const indicesRowArrReshaped = (0, _ndarray.default)(new Int32Array(squareDim ** 2), [squareDim, squareDim]); + const indicesColArrReshaped = (0, _ndarray.default)(new Int32Array(squareDim ** 2), [squareDim, squareDim]); + const indicesArrReshaped = (0, _ndarray.default)(new Int32Array(squareDim ** 2), [squareDim, squareDim]); + + for (let i = 0; i < squareDim; i++) { + _ndarrayOps.default.assigns(indicesRowArrReshaped.pick(i, null), i); + } + + for (let j = 0; j < squareDim; j++) { + _ndarrayOps.default.assigns(indicesColArrReshaped.pick(null, j), j); + } + + _ndarrayOps.default.muls(indicesArrReshaped, indicesRowArrReshaped, squareDim); + + _ndarrayOps.default.addeq(indicesArrReshaped, indicesColArrReshaped); + + indicesArr.data.set(indicesArrReshaped.data.subarray(0, indicesArr.size)); + } else { + if (axis < 0) { + axis = shape.length + axis; + } + + const axisSize = shape[axis]; + const indicesRowArr = (0, _ndarray.default)(new Int32Array(size), shape); + const indicesColArr = (0, _ndarray.default)(new Int32Array(size), shape); + const otherAxes = [...shape.slice(0, axis), ...shape.slice(axis + 1)]; + const otherAxesSize = otherAxes.reduce((a, b) => a * b, 1); + const indicesRowArrSlice = (0, _ndarray.default)(new Int32Array((0, _range2.default)(otherAxesSize)), otherAxes); + const axisSlices = Array(shape.length).fill(null); + + for (let n = 0; n < axisSize; n++) { + axisSlices[axis] = n; + + _ndarrayOps.default.assign(indicesRowArr.pick(...axisSlices), indicesRowArrSlice); + + _ndarrayOps.default.assigns(indicesColArr.pick(...axisSlices), n); + } + + _ndarrayOps.default.muls(indicesArr, indicesRowArr, axisSize); + + _ndarrayOps.default.addeq(indicesArr, indicesColArr); + } + + return indicesArr; +} \ No newline at end of file diff --git a/lib/utils/testUtils.js b/lib/utils/testUtils.js new file mode 100644 index 0000000000..36e30b5d69 --- /dev/null +++ b/lib/utils/testUtils.js @@ -0,0 +1,35 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.approxEquals = approxEquals; + +var _isFinite2 = _interopRequireDefault(require("lodash/isFinite")); + +var _flattenDeep2 = _interopRequireDefault(require("lodash/flattenDeep")); + +var _ndarrayUnpack = _interopRequireDefault(require("ndarray-unpack")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function approxEquals(ndarrayOut, dataExpected, tol = 0.0001) { + const a = (0, _flattenDeep2.default)((0, _ndarrayUnpack.default)(ndarrayOut)); + const b = dataExpected; + + if (a.length !== b.length) { + return false; + } + + for (let i = 0; i < a.length; i++) { + if (!(0, _isFinite2.default)(a[i])) { + return false; + } + + if (a[i] < b[i] - tol || a[i] > b[i] + tol) { + return false; + } + } + + return true; +} \ No newline at end of file diff --git a/lib/visualizations/CAM.js b/lib/visualizations/CAM.js new file mode 100644 index 0000000000..893ea2f6aa --- /dev/null +++ b/lib/visualizations/CAM.js @@ -0,0 +1,172 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _Tensor = _interopRequireDefault(require("../Tensor")); + +var _WebGL = require("../WebGL2"); + +var _ndarrayOps = _interopRequireDefault(require("ndarray-ops")); + +var _ndarrayBlasLevel = require("ndarray-blas-level2"); + +var _ndarrayGemm = _interopRequireDefault(require("ndarray-gemm")); + +var _createGLSLProgram = _interopRequireDefault(require("../webgl/dynamic/createGLSLProgram")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +class CAM { + constructor(attrs = {}) { + this.modelLayersMap = attrs.modelLayersMap; + this.gpu = attrs.gpu; + + if (!this.modelLayersMap) { + throw new Error(`[CAM] modelLayersMap is required`); + } + } + + initialize() { + this.modelLayersMap.forEach(layer => { + if (layer.layerClass === 'GlobalAveragePooling2D') { + this.enabled = true; + this.poolLayer = layer; + } + }); + + if (this.enabled && !this.data) { + this.featureMaps = this.modelLayersMap.get(this.poolLayer.inbound[0]).output; + let weightsFound = false; + let finalLayerReached = false; + let traversingLayer = this.poolLayer; + + while (!weightsFound && !finalLayerReached) { + traversingLayer = this.modelLayersMap.get(traversingLayer.outbound[0]); + + if (traversingLayer.weights['kernel']) { + this.weights = traversingLayer.weights['kernel']; + weightsFound = true; + } else if (!traversingLayer.outbound.length) { + this.weights = this.poolLayer.output; + finalLayerReached = true; + } + } + + if (this.featureMaps.is2DReshaped) { + this.inputShape = this.featureMaps.originalShape.slice(0, 2); + } else { + this.inputShape = this.featureMaps.tensor.shape.slice(0, 2); + } + + if (this.weights.tensor.shape.length === 1) { + this.shape = this.inputShape; + } else { + const numOutputClasses = this.weights.tensor.shape[1]; + this.shape = [...this.inputShape, numOutputClasses]; + } + + this.data = new Float32Array(this.shape.reduce((a, b) => a * b, 1)); + } + } + + update() { + if (!this.enabled) return; + this.featureMaps = this.modelLayersMap.get(this.poolLayer.inbound[0]).output; + + if (this.gpu) { + this._updateGPU(); + } else { + this._updateCPU(); + } + + const outputMin = _ndarrayOps.default.inf(this.output.tensor); + + const outputMax = _ndarrayOps.default.sup(this.output.tensor); + + _ndarrayOps.default.divseq(_ndarrayOps.default.subseq(this.output.tensor, outputMin), outputMax - outputMin); + + this.data = this.output.tensor.data; + } + + _updateCPU() { + if (!this.featureMaps.is2DReshaped) { + this.featureMaps.reshapeTo2D(); + } + + if (this.weights.tensor.shape.length === 1) { + if (!this.output) { + this.output = new _Tensor.default([], this.shape); + } + + const matVec = new _Tensor.default([], [this.shape[0] * this.shape[1]]); + (0, _ndarrayBlasLevel.gemv)(1, this.featureMaps.tensor, this.weights.tensor, 1, matVec.tensor); + this.output.replaceTensorData(matVec.tensor.data); + } else { + if (!this.output) { + this.output = new _Tensor.default([], this.shape); + } + + this.output.reshapeTo2D(); + (0, _ndarrayGemm.default)(this.output.tensor, this.featureMaps.tensor, this.weights.tensor, 1, 1); + this.output.reshapeFrom2D(); + } + + _ndarrayOps.default.maxseq(this.output.tensor, 0); + + if (this.featureMaps.is2DReshaped) { + this.featureMaps.reshapeFrom2D(); + } + } + + _updateGPU() { + if (!this.output) { + this.output = new _Tensor.default([], this.shape); + } + + const isWeights1D = this.weights.is1D; + + if (!this.output.glTexture && isWeights1D) { + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } else { + this.output.reshapeTo2D(); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + const numFeatures = isWeights1D ? this.weights.glTextureShape[1] : this.weights.glTextureShape[0]; + + if (!this.program) { + const programSource = (0, _createGLSLProgram.default)('cam', this.output.glTextureShape, numFeatures, isWeights1D); + this.program = _WebGL.webgl2.compileProgram(programSource); + } + + _WebGL.webgl2.runProgram({ + program: this.program, + output: this.output, + inputs: [{ + input: this.featureMaps, + name: 'featureMaps' + }, { + input: this.weights, + name: 'weights' + }] + }); + + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } + } + +} + +exports.default = CAM; \ No newline at end of file diff --git a/lib/visualizations/index.js b/lib/visualizations/index.js new file mode 100644 index 0000000000..541e2e55a7 --- /dev/null +++ b/lib/visualizations/index.js @@ -0,0 +1,15 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "CAM", { + enumerable: true, + get: function () { + return _CAM.default; + } +}); + +var _CAM = _interopRequireDefault(require("./CAM")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/warnings.js b/lib/warnings.js deleted file mode 100644 index 329b013fc1..0000000000 --- a/lib/warnings.js +++ /dev/null @@ -1,20 +0,0 @@ -const chalk = require('chalk') - -module.exports = { - v2SuffixTemplatesDeprecated (template, name) { - const initCommand = 'vue init ' + template.replace('-2.0', '') + ' ' + name - - console.log(chalk.red(' This template is deprecated, as the original template now uses Vue 2.0 by default.')) - console.log() - console.log(chalk.yellow(' Please use this command instead: ') + chalk.green(initCommand)) - console.log() - }, - v2BranchIsNowDefault (template, name) { - const vue1InitCommand = 'vue init ' + template + '#1.0' + ' ' + name - - console.log(chalk.green(' This will install Vue 2.x version of the template.')) - console.log() - console.log(chalk.yellow(' For Vue 1.x use: ') + chalk.green(vue1InitCommand)) - console.log() - } -} diff --git a/lib/webgl/dynamic/convolutional/conv2d.js b/lib/webgl/dynamic/convolutional/conv2d.js new file mode 100644 index 0000000000..764f64bb76 --- /dev/null +++ b/lib/webgl/dynamic/convolutional/conv2d.js @@ -0,0 +1,44 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = conv2d; + +function conv2d(outputShape, inputShape, indexMapShape, useBias, hasFragments) { + const addBias = useBias ? `sum += texelFetch(bias, ivec2(out_x, 0), 0).r;` : ''; + const adjustIndicesForFragments = hasFragments ? `int fragmentIndex = int(floor(float(rowIndex) / float(${inputShape[0]}))); + rowIndex = int(mod(float(rowIndex), float(${inputShape[0]}))); + colIndex += fragmentIndex * ${inputShape[1]};` : ''; + const source = `#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D x; +uniform isampler2D indexMap; +uniform sampler2D kernel; +uniform sampler2D bias; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int i = 0; i < ${indexMapShape[1]}; ++i) { + int index = texelFetch(indexMap, ivec2(i, out_y), 0).r; + if (index != -1) { + int rowIndex = int(floor(float(index) / float(${inputShape[1]}))); + int colIndex = int(mod(float(index), float(${inputShape[1]}))); + ${adjustIndicesForFragments} + sum += texelFetch(x, ivec2(colIndex, rowIndex), 0).r * texelFetch(kernel, ivec2(out_x, i), 0).r; + } + } + + ${addBias} + outColor = vec4(sum); +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/convolutional/conv2dTranspose.js b/lib/webgl/dynamic/convolutional/conv2dTranspose.js new file mode 100644 index 0000000000..fc9873be9a --- /dev/null +++ b/lib/webgl/dynamic/convolutional/conv2dTranspose.js @@ -0,0 +1,43 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = conv2dTranspose; + +function conv2dTranspose(outputShape, inputShape, indexMapShape, useBias, hasFragments) { + const addBias = useBias ? `sum += texelFetch(bias, ivec2(out_x, 0), 0).r;` : ''; + const adjustIndicesForFragments = hasFragments ? `int fragmentIndex = int(floor(float(rowIndex) / float(${inputShape[0]}))); + rowIndex = int(mod(float(rowIndex), float(${inputShape[0]}))); + colIndex += fragmentIndex * ${inputShape[1]};` : ''; + const source = `#version 300 es +precision highp float; +precision highp isampler2D; + +in vec2 outTex; +uniform sampler2D matMulResult; +uniform isampler2D indexMap; +uniform sampler2D bias; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int n = 0; n < ${indexMapShape[1]}; ++n) { + int index = texelFetch(indexMap, ivec2(n, out_y), 0).r; + if (index != -1) { + int rowIndex = int(floor(float(index) / float(${inputShape[1]}))); + int colIndex = int(mod(float(index), float(${inputShape[1]}))); + ${adjustIndicesForFragments} + sum += texelFetch(matMulResult, ivec2(colIndex + out_x, rowIndex), 0).r; + } + } + + ${addBias} + outColor = vec4(sum); +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/createGLSLProgram.js b/lib/webgl/dynamic/createGLSLProgram.js new file mode 100644 index 0000000000..8273e5a7e5 --- /dev/null +++ b/lib/webgl/dynamic/createGLSLProgram.js @@ -0,0 +1,65 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = createGLSLProgram; + +var _add = _interopRequireDefault(require("./merge/add")); + +var _average = _interopRequireDefault(require("./merge/average")); + +var _concatenate = _interopRequireDefault(require("./merge/concatenate")); + +var _maximum = _interopRequireDefault(require("./merge/maximum")); + +var _minimum = _interopRequireDefault(require("./merge/minimum")); + +var _multiply = _interopRequireDefault(require("./merge/multiply")); + +var _subtract = _interopRequireDefault(require("./merge/subtract")); + +var _conv2d = _interopRequireDefault(require("./convolutional/conv2d")); + +var _conv2dTranspose = _interopRequireDefault(require("./convolutional/conv2dTranspose")); + +var _cam = _interopRequireDefault(require("./visualizations/cam")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function createGLSLProgram(program, ...args) { + switch (program) { + case 'add': + return (0, _add.default)(...args); + + case 'average': + return (0, _average.default)(...args); + + case 'concatenate': + return (0, _concatenate.default)(...args); + + case 'maximum': + return (0, _maximum.default)(...args); + + case 'minimum': + return (0, _minimum.default)(...args); + + case 'multiply': + return (0, _multiply.default)(...args); + + case 'subtract': + return (0, _subtract.default)(...args); + + case 'conv2d': + return (0, _conv2d.default)(...args); + + case 'conv2dTranspose': + return (0, _conv2dTranspose.default)(...args); + + case 'cam': + return (0, _cam.default)(...args); + + default: + throw new Error('GLSL program not found'); + } +} \ No newline at end of file diff --git a/lib/webgl/dynamic/merge/add.js b/lib/webgl/dynamic/merge/add.js new file mode 100644 index 0000000000..2269359973 --- /dev/null +++ b/lib/webgl/dynamic/merge/add.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = add; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function add(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(${(0, _range2.default)(numInputs).map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`).join(' + ')}); +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/merge/average.js b/lib/webgl/dynamic/merge/average.js new file mode 100644 index 0000000000..0a96cf805c --- /dev/null +++ b/lib/webgl/dynamic/merge/average.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = average; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function average(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4((${(0, _range2.default)(numInputs).map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`).join(' + ')}) / float(${numInputs})); +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/merge/concatenate.js b/lib/webgl/dynamic/merge/concatenate.js new file mode 100644 index 0000000000..791572e061 --- /dev/null +++ b/lib/webgl/dynamic/merge/concatenate.js @@ -0,0 +1,67 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = concatenate; + +var _take2 = _interopRequireDefault(require("lodash/take")); + +var _sum2 = _interopRequireDefault(require("lodash/sum")); + +var _range2 = _interopRequireDefault(require("lodash/range")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function concatenate(numInputs, inputShapes, outputShape, concatAxis) { + const dims = inputShapes.map(shape => shape[concatAxis]); + const offsets = (0, _range2.default)(numInputs + 1).map(i => (0, _sum2.default)((0, _take2.default)(dims, i))); + const outVar = concatAxis === 0 ? 'out_y' : 'out_x'; + let getOffset = ` + int n = 0; + int offset = 0; + if (${outVar} >= ${offsets[1]} && ${outVar} < ${offsets[2]}) { + n = 1; + offset = ${offsets[1]}; + }`; + + if (numInputs > 2) { + getOffset += `${(0, _range2.default)(2, numInputs).map(i => ` else if (${outVar} >= ${offsets[i]} && ${outVar} < ${offsets[i + 1]}) { + n = ${i}; + offset = ${offsets[i]}; + }`).join('')} +`; + } + + let outBlock = 'outColor = vec4(0.0);'; + + if (concatAxis === 0 || concatAxis === 1) { + const xCoord = i => `out_x${concatAxis === 1 ? ` - ${offsets[i]}` : ''}`; + + const yCoord = i => `out_y${concatAxis === 0 ? ` - ${offsets[i]}` : ''}`; + + outBlock = ` + if (n == 0) { + outColor = vec4(texelFetch(inputs[0], ivec2(out_x, out_y), 0).r); + }${(0, _range2.default)(1, numInputs).map(i => ` else if (n == ${i}) { + outColor = vec4(texelFetch(inputs[${i}], ivec2(${xCoord(i)}, ${yCoord(i)}), 0).r); + }`).join('')} +`; + } + + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); +${getOffset} +${outBlock} +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/merge/maximum.js b/lib/webgl/dynamic/merge/maximum.js new file mode 100644 index 0000000000..b6c70ab45c --- /dev/null +++ b/lib/webgl/dynamic/merge/maximum.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = maximum; + +function maximum(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + float val = texelFetch(inputs[0], ivec2(out_x, out_y), 0).r; + for (int i = 1; i < ${numInputs}; i++) { + val = max(val, texelFetch(inputs[i], ivec2(out_x, out_y), 0).r); + } + + outColor = vec4(val); +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/merge/minimum.js b/lib/webgl/dynamic/merge/minimum.js new file mode 100644 index 0000000000..b9c97e3005 --- /dev/null +++ b/lib/webgl/dynamic/merge/minimum.js @@ -0,0 +1,29 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = minimum; + +function minimum(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + float val = texelFetch(inputs[0], ivec2(out_x, out_y), 0).r; + for (int i = 1; i < ${numInputs}; i++) { + val = min(val, texelFetch(inputs[i], ivec2(out_x, out_y), 0).r); + } + + outColor = vec4(val); +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/merge/multiply.js b/lib/webgl/dynamic/merge/multiply.js new file mode 100644 index 0000000000..8a0b9e7cc5 --- /dev/null +++ b/lib/webgl/dynamic/merge/multiply.js @@ -0,0 +1,28 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = multiply; + +var _range2 = _interopRequireDefault(require("lodash/range")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function multiply(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[${numInputs}]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(${(0, _range2.default)(numInputs).map(i => `texelFetch(inputs[${i}], ivec2(out_x, out_y), 0).r`).join(' * ')}); +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/merge/subtract.js b/lib/webgl/dynamic/merge/subtract.js new file mode 100644 index 0000000000..5c4b17395c --- /dev/null +++ b/lib/webgl/dynamic/merge/subtract.js @@ -0,0 +1,24 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = subtract; + +function subtract(numInputs, shape) { + const source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D inputs[2]; +out vec4 outColor; + +void main() { + int out_y = int(float(${shape[0]}) * outTex.y); + int out_x = int(float(${shape[1]}) * outTex.x); + + outColor = vec4(texelFetch(inputs[0], ivec2(out_x, out_y), 0).r - texelFetch(inputs[1], ivec2(out_x, out_y), 0).r); +} +`; + return source; +} \ No newline at end of file diff --git a/lib/webgl/dynamic/visualizations/cam.js b/lib/webgl/dynamic/visualizations/cam.js new file mode 100644 index 0000000000..123cbb08a5 --- /dev/null +++ b/lib/webgl/dynamic/visualizations/cam.js @@ -0,0 +1,62 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = cam; + +function cam(outputShape, numFeatures, weightsIs1D) { + let source; + + if (weightsIs1D) { + source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D featureMaps; +uniform sampler2D weights; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + int featureMapsRow = out_x + ${outputShape[0]} * out_y; + + float sum = 0.; + for (int k = 0; k < ${numFeatures}; ++k) { + float f = texelFetch(featureMaps, ivec2(k, featureMapsRow), 0).r; + float w = texelFetch(weights, ivec2(k, 0), 0).r; + sum += f * w; + } + + outColor = vec4(max(sum, 0.0)); +} +`; + } else { + source = `#version 300 es +precision highp float; + +in vec2 outTex; +uniform sampler2D featureMaps; +uniform sampler2D weights; +out vec4 outColor; + +void main() { + int out_y = int(float(${outputShape[0]}) * outTex.y); + int out_x = int(float(${outputShape[1]}) * outTex.x); + + float sum = 0.; + for (int k = 0; k < ${numFeatures}; ++k) { + float f = texelFetch(featureMaps, ivec2(k, out_y), 0).r; + float w = texelFetch(weights, ivec2(out_x, k), 0).r; + sum += f * w; + } + + outColor = vec4(max(sum, 0.0)); +} +`; + } + + return source; +} \ No newline at end of file diff --git a/myproj/.babelrc b/myproj/.babelrc new file mode 100644 index 0000000000..9237a30ed3 --- /dev/null +++ b/myproj/.babelrc @@ -0,0 +1,18 @@ +{ + "presets": [ + ["env", { + "modules": false + }], + // "stage-2" + {} + ], + "plugins": [ + "transform-runtime" + ], + "env": { + "test": { + "presets": ["env", "stage-2"], + "plugins": ["transform-es2015-modules-commonjs", "dynamic-import-node"] + } + } +} diff --git a/myproj/.gitignore b/myproj/.gitignore new file mode 100644 index 0000000000..dfb4167f9a --- /dev/null +++ b/myproj/.gitignore @@ -0,0 +1,17 @@ +.DS_Store +node_modules/ +/dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +/test/unit/coverage/ +/test/e2e/reports/ +selenium-debug.log + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln diff --git a/myproj/.postcssrc.js b/myproj/.postcssrc.js new file mode 100644 index 0000000000..ca97968852 --- /dev/null +++ b/myproj/.postcssrc.js @@ -0,0 +1,5 @@ +// https://github.com/michael-ciniawsky/postcss-load-config + +module.exports = { + plugins: [require('postcss-import')(), require('postcss-cssnext')()] +} diff --git a/myproj/README.md b/myproj/README.md new file mode 100644 index 0000000000..09e8da5382 --- /dev/null +++ b/myproj/README.md @@ -0,0 +1,30 @@ +# myproj + +> A Vue.js project + +## Build Setup + +``` bash +# install dependencies +npm install + +# serve with hot reload at localhost:8080 +npm run dev + +# build for production with minification +npm run build + +# build for production and view the bundle analyzer report +npm run build --report + +# run unit tests +npm run unit + +# run e2e tests +npm run e2e + +# run all tests +npm test +``` + +For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). diff --git a/myproj/external/keras.min.js b/myproj/external/keras.min.js new file mode 100644 index 0000000000..cce5dbff28 --- /dev/null +++ b/myproj/external/keras.min.js @@ -0,0 +1,46460 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["KerasJS"] = factory(); + else + root["KerasJS"] = factory(); +})(typeof self !== 'undefined' ? self : this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 182); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(6); +var core = __webpack_require__(41); +var hide = __webpack_require__(16); +var redefine = __webpack_require__(29); +var ctx = __webpack_require__(23); +var PROTOTYPE = 'prototype'; + +var $export = function (type, name, source) { + var IS_FORCED = type & $export.F; + var IS_GLOBAL = type & $export.G; + var IS_STATIC = type & $export.S; + var IS_PROTO = type & $export.P; + var IS_BIND = type & $export.B; + var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE]; + var exports = IS_GLOBAL ? core : core[name] || (core[name] = {}); + var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}); + var key, own, out, exp; + if (IS_GLOBAL) source = name; + for (key in source) { + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + // export native or passed + out = (own ? target : source)[key]; + // bind timers to global for call from export context + exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // extend global + if (target) redefine(target, key, out, type & $export.U); + // export + if (exports[key] != out) hide(exports, key, exp); + if (IS_PROTO && expProto[key] != out) expProto[key] = out; + } +}; +global.core = core; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; + + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Tensor; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__utils_tensorUtils__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_ndarray__ = __webpack_require__(66); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_ndarray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_ndarray__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_ndarray_ops__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_ndarray_squeeze__ = __webpack_require__(167); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_ndarray_squeeze___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_ndarray_squeeze__); +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + + + + + + + +var Tensor = function () { + function Tensor(data, shape) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + _classCallCheck(this, Tensor); + + this.arrayType = options.type || Float32Array; + + if (data && data.length && (data instanceof this.arrayType || data instanceof Array)) { + __WEBPACK_IMPORTED_MODULE_1__utils_tensorUtils__["a" /* checkShape */](data, shape); + + if (data instanceof this.arrayType) { + this.tensor = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(data, shape); + } else if (data instanceof Array) { + this.tensor = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(data), shape); + } + } else if (!data.length && shape.length) { + this.tensor = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(shape.reduce(function (a, b) { + return a * b; + }, 1)), shape); + } else { + this.tensor = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType([]), []); + } + } + + _createClass(Tensor, [{ + key: "createGLTexture", + value: function createGLTexture(_ref) { + var _ref$type = _ref.type, + type = _ref$type === void 0 ? '2d' : _ref$type, + _ref$format = _ref.format, + format = _ref$format === void 0 ? 'float' : _ref$format, + _ref$supportsTextureF = _ref.supportsTextureFragments, + supportsTextureFragments = _ref$supportsTextureF === void 0 ? false : _ref$supportsTextureF; + var shape = []; + + if (this.tensor.shape.length === 1) { + shape = [1, this.tensor.shape[0]]; + this.is1D = true; + } else if (this.tensor.shape.length === 2) { + shape = this.tensor.shape; + } else if (this.tensor.shape.length === 3 && (type === '2d_array' || type === '3d')) { + shape = this.tensor.shape; + } else { + throw new Error('[Tensor] cannot create WebGL2 texture.'); + } + + this.glTextureShape = shape; + this.glTextureType = type; + this.glTextureFormat = format; + + if (type === '2d') { + if (this.glTextureShape[0] > __WEBPACK_IMPORTED_MODULE_0__WebGL2__["a" /* MAX_TEXTURE_SIZE */] && supportsTextureFragments) { + this._create2DRowFragmentedGLTexture(); + } else { + this._create2DGLTexture(); + } + } else if (type === '2d_array' || type === '3d') { + this._create3DGLTexture(); + } else { + throw new Error("[Tensor] invalid type ".concat(type, ".")); + } + } + }, { + key: "_create2DGLTexture", + value: function _create2DGLTexture() { + var gl = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].context; + var textureOptions = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + var textureTarget = textureOptions.textureTarget, + textureInternalFormat = textureOptions.textureInternalFormat, + textureFormat = textureOptions.textureFormat, + textureType = textureOptions.textureType; + this.glTexture = gl.createTexture(); + __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].storeRef('texture', this.glTexture); + gl.bindTexture(textureTarget, this.glTexture); + var shape = this.glTextureShape; + var data = this.tensor.data; + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } + }, { + key: "_create2DRowFragmentedGLTexture", + value: function _create2DRowFragmentedGLTexture() { + var gl = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].context; + var textureOptions = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + var textureTarget = textureOptions.textureTarget, + textureInternalFormat = textureOptions.textureInternalFormat, + textureFormat = textureOptions.textureFormat, + textureType = textureOptions.textureType; + this.glTextureFragments = []; + this.glTextureFragmentShape = [__WEBPACK_IMPORTED_MODULE_0__WebGL2__["a" /* MAX_TEXTURE_SIZE */], this.glTextureShape[1]]; + var shape = this.glTextureFragmentShape; + var numFragments = Math.ceil(this.glTextureShape[0] / __WEBPACK_IMPORTED_MODULE_0__WebGL2__["a" /* MAX_TEXTURE_SIZE */]); + var offset = 0; + + for (var k = 0; k < numFragments; k++) { + var glTexture = gl.createTexture(); + __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].storeRef('texture', glTexture); + gl.bindTexture(textureTarget, glTexture); + var data = void 0; + + if (k === numFragments - 1) { + data = new this.arrayType(shape[0] * shape[1]); + data.set(this.tensor.data.slice(offset, offset + shape[0] * shape[1]), 0); + } else { + data = this.tensor.data.slice(offset, offset + shape[0] * shape[1]); + } + + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + this.glTextureFragments.push(glTexture); + offset += shape[0] * shape[1]; + } + } + }, { + key: "_create3DGLTexture", + value: function _create3DGLTexture() { + var gl = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].context; + var textureOptions = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + var textureTarget = textureOptions.textureTarget, + textureInternalFormat = textureOptions.textureInternalFormat, + textureFormat = textureOptions.textureFormat, + textureType = textureOptions.textureType; + this.glTexture = gl.createTexture(); + __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].storeRef('texture', this.glTexture); + gl.bindTexture(textureTarget, this.glTexture); + var shape = this.glTextureShape; + var data = __WEBPACK_IMPORTED_MODULE_1__utils_tensorUtils__["c" /* data3DLayoutForGL */](this.arrayType, this.tensor, this.glTextureShape); + gl.texImage3D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], shape[2], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } + }, { + key: "convert2DRowFragmentedGLTextureToColStack", + value: function convert2DRowFragmentedGLTextureToColStack() { + var _this = this; + + if (!this.glTextureFragments || !this.glTextureFragmentShape) { + throw new Error('[Tensor] no glTextureFragments available.'); + } + + var gl = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].context; + var textureOptions = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + var textureTarget = textureOptions.textureTarget, + textureInternalFormat = textureOptions.textureInternalFormat, + textureFormat = textureOptions.textureFormat, + textureType = textureOptions.textureType; + + if (!this.glTextureFragmentsAsColStack) { + this.glTextureFragmentsAsColStack = gl.createTexture(); + __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].storeRef('texture', this.glTextureFragmentsAsColStack); + gl.bindTexture(textureTarget, this.glTextureFragmentsAsColStack); + var numFragments = this.glTextureFragments.length; + this.glTextureFragmentsAsColStackShape = [this.glTextureFragmentShape[0], this.glTextureFragmentShape[1] * numFragments]; + var shape = this.glTextureFragmentsAsColStackShape; + var data = new this.arrayType(shape.reduce(function (a, b) { + return a * b; + }, 1)); + gl.texImage2D(textureTarget, 0, textureInternalFormat, shape[1], shape[0], 0, textureFormat, textureType, data); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + } else { + gl.bindTexture(textureTarget, this.glTextureFragmentsAsColStack); + } + + var fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo); + this.glTextureFragments.forEach(function (texture, k) { + gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + gl.copyTexSubImage2D(textureTarget, 0, k * _this.glTextureFragmentShape[1], 0, 0, 0, _this.glTextureFragmentShape[1], _this.glTextureFragmentShape[0]); + }); + gl.deleteFramebuffer(fbo); + } + }, { + key: "removeGLTextureFragmentsAsColStack", + value: function removeGLTextureFragmentsAsColStack() { + if (this.glTextureFragmentsAsColStack) { + var gl = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].context; + gl.deleteTexture(this.glTextureFragmentsAsColStack); + delete this.glTextureFragmentsAsColStack; + delete this.glTextureFragmentsAsColStackShape; + } + } + }, { + key: "deleteGLTexture", + value: function deleteGLTexture() { + var gl = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].context; + + if (this.glTexture) { + gl.deleteTexture(this.glTexture); + delete this.glTexture; + } + + if (this.glTextureFragments) { + this.glTextureFragments.forEach(function (texture) { + gl.deleteTexture(texture); + }); + delete this.glTextureFragments; + } + } + }, { + key: "replaceTensorData", + value: function replaceTensorData(data) { + if (data && data.length && data instanceof this.arrayType) { + this.tensor.data.set(data); + } else if (data && data.length && data instanceof Array) { + this.tensor.data.set(new this.arrayType(data)); + } else { + throw new Error('[Tensor] invalid input for replaceTensorData method.'); + } + + if (this.glTexture) { + var gl = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].context; + var textureOptions = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].getWebGLTextureOptions(this.glTextureType, this.glTextureFormat); + var textureTarget = textureOptions.textureTarget, + textureFormat = textureOptions.textureFormat, + textureType = textureOptions.textureType; + gl.bindTexture(textureTarget, this.glTexture); + var shape = this.glTextureShape; + + if (this.glTextureType === '2d') { + var _data = this.tensor.data; + gl.texSubImage2D(textureTarget, 0, 0, 0, shape[1], shape[0], textureFormat, textureType, _data, 0); + } else if (this.glTextureType === '2d_array' || this.glTextureType === '3d') { + var _data2 = __WEBPACK_IMPORTED_MODULE_1__utils_tensorUtils__["c" /* data3DLayoutForGL */](this.arrayType, this.tensor, shape); + + gl.texSubImage3D(textureTarget, 0, 0, 0, 0, shape[1], shape[0], shape[2], textureFormat, textureType, _data2, 0); + } + } + } + }, { + key: "transferFromGLTexture", + value: function transferFromGLTexture() { + if (this.glTextureFragments) { + this.tensor = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(this.glTextureShape[0] * this.glTextureShape[1]), this.glTextureShape); + var offset = 0; + + for (var k = 0; k < this.glTextureFragments.length; k++) { + __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].bindOutputTexture(this.glTextureFragments[k], this.glTextureFragmentShape); + var fragmentData = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].readData(this.glTextureFragmentShape); + + if (k === this.glTextureFragments.length - 1) { + var truncate = this.tensor.data.length - offset; + this.tensor.data.set(fragmentData.subarray(0, truncate), offset); + } else { + this.tensor.data.set(fragmentData, offset); + } + + offset += fragmentData.length; + } + } else { + __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].bindOutputTexture(this.glTexture, this.glTextureShape); + this.tensor = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType([]), this.glTextureShape); + this.tensor.data = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].readData(this.glTextureShape); + } + + if (this.is1D && this.glTextureShape[0] === 1) { + this.tensor = __WEBPACK_IMPORTED_MODULE_4_ndarray_squeeze___default()(this.tensor, [0]); + } + } + }, { + key: "reshapeTo2D", + value: function reshapeTo2D() { + var axis = this.tensor.shape.length - 1; + var axisSize = this.tensor.shape[axis]; + var otherAxes = this.tensor.shape.slice(0, axis); + var otherAxesSize = otherAxes.reduce(function (a, b) { + return a * b; + }, 1); + var reshaped = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(otherAxesSize * axisSize), [otherAxesSize, axisSize]); + var otherAxesData = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(otherAxesSize), otherAxes); + var otherAxesDataRaveled = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(otherAxesSize), [otherAxesSize]); + var axisSlices = Array(this.tensor.shape.length).fill(null); + + for (var n = 0; n < axisSize; n++) { + var _tensor; + + axisSlices[axis] = n; + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.assign(otherAxesData, (_tensor = this.tensor).pick.apply(_tensor, _toConsumableArray(axisSlices))); + otherAxesDataRaveled.data = otherAxesData.data; + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.assign(reshaped.pick(null, n), otherAxesDataRaveled); + } + + this.originalShape = this.tensor.shape; + this.indicesForReshaped = __WEBPACK_IMPORTED_MODULE_1__utils_tensorUtils__["b" /* createIndicesFor2DReshaped */](this.tensor.shape, false, axis); + this.tensor = reshaped; + this.is2DReshaped = true; + } + }, { + key: "reshapeFrom2D", + value: function reshapeFrom2D() { + var axis = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : -1; + + if (!this.is2DReshaped) { + throw new Error('[Tensor] not in reshaped 2D representation.'); + } + + if (!this.originalShape) { + throw new Error('[Tensor] does not contain originalShape.'); + } + + if (axis < 0) { + axis = this.originalShape.length + axis; + } + + var channelDataSize = this.tensor.shape[0]; + var channels = this.tensor.shape[1]; + var reshaped = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(this.originalShape.reduce(function (a, b) { + return a * b; + }, 1)), this.originalShape); + var channelDataRaveled = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(channelDataSize), [channelDataSize]); + + var unraveledChannelShape = _toConsumableArray(this.originalShape.slice(0, axis)).concat(_toConsumableArray(this.originalShape.slice(axis + 1))); + + var unraveledChannel = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(unraveledChannelShape.reduce(function (a, b) { + return a * b; + }, 1)), unraveledChannelShape); + var axisSlices = Array(this.originalShape.length).fill(null); + + for (var n = 0; n < channels; n++) { + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.assign(channelDataRaveled, this.tensor.pick(null, n)); + unraveledChannel.data = channelDataRaveled.data; + axisSlices[axis] = n; + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.assign(reshaped.pick.apply(reshaped, _toConsumableArray(axisSlices)), unraveledChannel); + } + + this.tensor = reshaped; + } + }, { + key: "reshapeTo2DSquare", + value: function reshapeTo2DSquare() { + var squareDim = Math.ceil(Math.sqrt(this.tensor.size)); + var reshaped = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(Math.pow(squareDim, 2)), [squareDim, squareDim]); + reshaped.data.set(this.tensor.data); + this.originalShape = this.tensor.shape; + this.indicesForReshaped = __WEBPACK_IMPORTED_MODULE_1__utils_tensorUtils__["b" /* createIndicesFor2DReshaped */](this.tensor.shape, true); + this.tensor = reshaped; + this.is2DSquareReshaped = true; + } + }, { + key: "reshapeFrom2DSquare", + value: function reshapeFrom2DSquare() { + if (!this.is2DSquareReshaped) { + throw new Error('[Tensor] not in reshaped 2D square representation.'); + } + + if (!this.originalShape) { + throw new Error('[Tensor] does not contain originalShape.'); + } + + var size = this.originalShape.reduce(function (a, b) { + return a * b; + }, 1); + var reshaped = __WEBPACK_IMPORTED_MODULE_2_ndarray___default()(new this.arrayType(size), this.originalShape); + reshaped.data.set(this.tensor.data.subarray(0, size)); + this.tensor = reshaped; + } + }]); + + return Tensor; +}(); + + + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return webgl2; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return MAX_TEXTURE_SIZE; }); +/* unused harmony export MAX_TEXTURE_IMAGE_UNITS */ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +var vertexShaderSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec3 position;\r\nin vec2 texcoord;\r\nout vec2 outTex;\r\n\r\nvoid main () {\r\n gl_Position = vec4(position, 1.0);\r\n\toutTex = texcoord;\r\n}\r\n"; + +var WebGL2 = function () { + function WebGL2() { + _classCallCheck(this, WebGL2); + + this.isSupported = false; + this.vertexShader = null; + + if (typeof window !== 'undefined') { + this.canvas = document.createElement('canvas'); + this.context = this.canvas.getContext('webgl2'); + var gl = this.context; + + if (gl) { + this.isSupported = true; + gl.getExtension('EXT_color_buffer_float'); + this.MAX_TEXTURE_SIZE = gl.getParameter(gl.MAX_TEXTURE_SIZE); + this.MAX_TEXTURE_IMAGE_UNITS = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + this.init(); + } else { + console.log('Unable to initialize WebGL2 -- your browser may not support it.'); + } + } + + this._refs = { + textures: [], + buffers: [] + }; + } + + _createClass(WebGL2, [{ + key: "init", + value: function init() { + this.createCommonVertexShader(); + } + }, { + key: "createCommonVertexShader", + value: function createCommonVertexShader() { + var gl = this.context; + var vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertexShader, vertexShaderSource); + gl.compileShader(vertexShader); + var success = gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS); + + if (!success) { + console.error(gl.getShaderInfoLog(vertexShader)); + gl.deleteShader(vertexShader); + this.isSupported = false; + } + + this.vertexShader = vertexShader; + } + }, { + key: "compileProgram", + value: function compileProgram(source) { + var gl = this.context; + var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragmentShader, source); + gl.compileShader(fragmentShader); + var success = gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS); + + if (!success) { + console.error(gl.getShaderInfoLog(fragmentShader)); + gl.deleteShader(fragmentShader); + this.isSupported = false; + } + + var program = gl.createProgram(); + gl.attachShader(program, this.vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + success = gl.getProgramParameter(program, gl.LINK_STATUS); + + if (!success) { + console.error(gl.getProgramInfoLog(program)); + this.isSupported = false; + } + + this.setupVertices(program); + return program; + } + }, { + key: "setupVertices", + value: function setupVertices(program) { + var gl = this.context; + var position = gl.getAttribLocation(program, 'position'); + var positionVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, positionVertexObj); + this.storeRef('buffer', positionVertexObj); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]), gl.STATIC_DRAW); + gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(position); + var texcoord = gl.getAttribLocation(program, 'texcoord'); + var texcoordVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, texcoordVertexObj); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]), gl.STATIC_DRAW); + gl.vertexAttribPointer(texcoord, 2, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(texcoord); + this.storeRef('buffer', texcoordVertexObj); + var indicesVertexObj = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesVertexObj); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW); + this.storeRef('buffer', indicesVertexObj); + } + }, { + key: "selectProgram", + value: function selectProgram(program) { + var gl = this.context; + gl.useProgram(program); + } + }, { + key: "bindUniforms", + value: function bindUniforms(program, uniforms) { + var gl = this.context; + uniforms.forEach(function (_ref) { + var value = _ref.value, + type = _ref.type, + name = _ref.name; + var loc = gl.getUniformLocation(program, name); + + if (type === 'float') { + gl.uniform1f(loc, value); + } else if (type === 'int' || type === 'bool') { + gl.uniform1i(loc, value); + } + }); + } + }, { + key: "bindInputTextures", + value: function bindInputTextures(program, inputs, k) { + var _this = this; + + var gl = this.context; + inputs.forEach(function (_ref2, i) { + var input = _ref2.input, + name = _ref2.name; + gl.activeTexture(gl.TEXTURE0 + i); + + if (input.glTextureFragments) { + if (input.glTextureFragmentsAsColStack) { + var _this$getWebGLTexture = _this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat), + textureTarget = _this$getWebGLTexture.textureTarget; + + gl.bindTexture(textureTarget, input.glTextureFragmentsAsColStack); + } else { + var _this$getWebGLTexture2 = _this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat), + _textureTarget = _this$getWebGLTexture2.textureTarget; + + gl.bindTexture(_textureTarget, input.glTextureFragments[k]); + } + } else { + var _this$getWebGLTexture3 = _this.getWebGLTextureOptions(input.glTextureType, input.glTextureFormat), + _textureTarget2 = _this$getWebGLTexture3.textureTarget; + + gl.bindTexture(_textureTarget2, input.glTexture); + } + + gl.uniform1i(gl.getUniformLocation(program, name), i); + }); + } + }, { + key: "bindOutputTexture", + value: function bindOutputTexture(outputTexture, shape) { + var gl = this.context; + gl.viewport(0, 0, shape[1], shape[0]); + this.framebuffer = this.framebuffer || gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0); + } + }, { + key: "runProgram", + value: function runProgram(_ref3) { + var program = _ref3.program, + output = _ref3.output, + inputs = _ref3.inputs, + uniforms = _ref3.uniforms, + _ref3$supportsTexture = _ref3.supportsTextureFragments, + supportsTextureFragments = _ref3$supportsTexture === void 0 ? false : _ref3$supportsTexture; + if (!program) throw new Error('[WebGL2] missing program'); + if (!output) throw new Error('[WebGL2] missing output'); + if (!inputs) throw new Error('[WebGL2] missing inputs'); + var gl = this.context; + this.selectProgram(program); + + if (uniforms && Array.isArray(uniforms)) { + this.bindUniforms(program, uniforms); + } + + if (output.glTextureFragments) { + if (!supportsTextureFragments) { + throw new Error('[WebGL2] program does not support texture fragments'); + } + + var inputsWithFragments = inputs.filter(function (obj) { + return obj.input.glTextureFragments && !obj.input.glTextureFragmentsAsColStack; + }); + var numFragments = output.glTextureFragments.length; + + if (inputsWithFragments.some(function (obj) { + return obj.input.glTextureFragments.length !== numFragments; + })) { + throw new Error('[WebGL2] number of texture fragments in inputs and output do not match'); + } + + for (var k = 0; k < numFragments; k++) { + this.bindOutputTexture(output.glTextureFragments[k], output.glTextureFragmentShape); + this.bindInputTextures(program, inputs, k); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + } + } else { + this.bindOutputTexture(output.glTexture, output.glTextureShape); + this.bindInputTextures(program, inputs); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + } + } + }, { + key: "readData", + value: function readData(shape) { + var gl = this.context; + var buf = new ArrayBuffer(shape[0] * shape[1] * 4 * 4); + var view = new Float32Array(buf); + gl.readPixels(0, 0, shape[1], shape[0], gl.RGBA, gl.FLOAT, view); + var out = []; + + for (var i = 0; i < view.length; i += 4) { + out.push(view[i]); + } + + return new Float32Array(out); + } + }, { + key: "getWebGLTextureOptions", + value: function getWebGLTextureOptions(type, format) { + var gl = this.context; + var targetMap = { + '2d': gl.TEXTURE_2D, + '2d_array': gl.TEXTURE_2D_ARRAY, + '3d': gl.TEXTURE_3D + }; + var internalFormatMap = { + float: gl.R32F, + int: gl.R32I + }; + var formatMap = { + float: gl.RED, + int: gl.RED_INTEGER + }; + var typeMap = { + float: gl.FLOAT, + int: gl.INT + }; + var textureTarget = targetMap[type]; + var textureInternalFormat = internalFormatMap[format]; + var textureFormat = formatMap[format]; + var textureType = typeMap[format]; + return { + textureTarget: textureTarget, + textureInternalFormat: textureInternalFormat, + textureFormat: textureFormat, + textureType: textureType + }; + } + }, { + key: "storeRef", + value: function storeRef(type, obj) { + if (type === 'texture') { + this._refs.textures.push(obj); + } else if (type === 'buffer') { + this._refs.buffers.push(obj); + } + } + }, { + key: "clearRefs", + value: function clearRefs() { + var gl = this.context; + + this._refs.textures.forEach(function (texture) { + return gl.deleteTexture(texture); + }); + + this._refs.buffers.forEach(function (buffer) { + return gl.deleteBuffer(buffer); + }); + + this._refs = { + textures: [], + buffers: [] + }; + } + }]); + + return WebGL2; +}(); + +var webgl2 = new WebGL2(); +var MAX_TEXTURE_SIZE = webgl2.MAX_TEXTURE_SIZE; +var MAX_TEXTURE_IMAGE_UNITS = webgl2.MAX_TEXTURE_IMAGE_UNITS; + + +/***/ }), +/* 3 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Layer; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__WebGL2__ = __webpack_require__(2); +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + + + +var Layer = function () { + function Layer() { + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, Layer); + + this.layerClass = 'Layer'; + this.name = attrs.name; + this.gpu = __WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].isSupported && attrs.gpu; + this.params = []; + this.weights = {}; + this.inbound = []; + this.outbound = []; + } + + _createClass(Layer, [{ + key: "throwError", + value: function throwError(message) { + throw new Error("[".concat(this.layerClass, " layer: ").concat(this.name || '', "] ").concat(message)); + } + }, { + key: "toggleGPU", + value: function toggleGPU(mode) { + var newMode = typeof mode === 'undefined' ? !this.gpu : mode; + + if (__WEBPACK_IMPORTED_MODULE_0__WebGL2__["b" /* webgl2 */].isSupported && newMode) { + this.gpu = true; + } else { + this.gpu = false; + } + } + }, { + key: "setWeights", + value: function setWeights(weightsArr) { + var _this = this; + + var createGLTexture = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + this.params.forEach(function (p, i) { + _this.weights[p] = weightsArr[i]; + + if (_this.gpu && createGLTexture) { + _this.weights[p].createGLTexture({ + type: '2d', + format: 'float' + }); + } + }); + } + }, { + key: "call", + value: function call(x) { + this.output = x; + return this.output; + } + }]); + + return Layer; +}(); + + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var compile = __webpack_require__(165) + +var EmptyProc = { + body: "", + args: [], + thisVars: [], + localVars: [] +} + +function fixup(x) { + if(!x) { + return EmptyProc + } + for(var i=0; i>", + rrshift: ">>>" +} +;(function(){ + for(var id in assign_ops) { + var op = assign_ops[id] + exports[id] = makeOp({ + args: ["array","array","array"], + body: {args:["a","b","c"], + body: "a=b"+op+"c"}, + funcName: id + }) + exports[id+"eq"] = makeOp({ + args: ["array","array"], + body: {args:["a","b"], + body:"a"+op+"=b"}, + rvalue: true, + funcName: id+"eq" + }) + exports[id+"s"] = makeOp({ + args: ["array", "array", "scalar"], + body: {args:["a","b","s"], + body:"a=b"+op+"s"}, + funcName: id+"s" + }) + exports[id+"seq"] = makeOp({ + args: ["array","scalar"], + body: {args:["a","s"], + body:"a"+op+"=s"}, + rvalue: true, + funcName: id+"seq" + }) + } +})(); + +var unary_ops = { + not: "!", + bnot: "~", + neg: "-", + recip: "1.0/" +} +;(function(){ + for(var id in unary_ops) { + var op = unary_ops[id] + exports[id] = makeOp({ + args: ["array", "array"], + body: {args:["a","b"], + body:"a="+op+"b"}, + funcName: id + }) + exports[id+"eq"] = makeOp({ + args: ["array"], + body: {args:["a"], + body:"a="+op+"a"}, + rvalue: true, + count: 2, + funcName: id+"eq" + }) + } +})(); + +var binary_ops = { + and: "&&", + or: "||", + eq: "===", + neq: "!==", + lt: "<", + gt: ">", + leq: "<=", + geq: ">=" +} +;(function() { + for(var id in binary_ops) { + var op = binary_ops[id] + exports[id] = makeOp({ + args: ["array","array","array"], + body: {args:["a", "b", "c"], + body:"a=b"+op+"c"}, + funcName: id + }) + exports[id+"s"] = makeOp({ + args: ["array","array","scalar"], + body: {args:["a", "b", "s"], + body:"a=b"+op+"s"}, + funcName: id+"s" + }) + exports[id+"eq"] = makeOp({ + args: ["array", "array"], + body: {args:["a", "b"], + body:"a=a"+op+"b"}, + rvalue:true, + count:2, + funcName: id+"eq" + }) + exports[id+"seq"] = makeOp({ + args: ["array", "scalar"], + body: {args:["a","s"], + body:"a=a"+op+"s"}, + rvalue:true, + count:2, + funcName: id+"seq" + }) + } +})(); + +var math_unary = [ + "abs", + "acos", + "asin", + "atan", + "ceil", + "cos", + "exp", + "floor", + "log", + "round", + "sin", + "sqrt", + "tan" +] +;(function() { + for(var i=0; ithis_s){this_s=-a}else if(a>this_s){this_s=a}", localVars: [], thisVars: ["this_s"]}, + post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"}, + funcName: "norminf" +}) + +exports.norm1 = compile({ + args:["array"], + pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"}, + body: {args:[{name:"a", lvalue:false, rvalue:true, count:3}], body: "this_s+=a<0?-a:a", localVars: [], thisVars: ["this_s"]}, + post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"}, + funcName: "norm1" +}) + +exports.sup = compile({ + args: [ "array" ], + pre: + { body: "this_h=-Infinity", + args: [], + thisVars: [ "this_h" ], + localVars: [] }, + body: + { body: "if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_", + args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ], + thisVars: [ "this_h" ], + localVars: [] }, + post: + { body: "return this_h", + args: [], + thisVars: [ "this_h" ], + localVars: [] } + }) + +exports.inf = compile({ + args: [ "array" ], + pre: + { body: "this_h=Infinity", + args: [], + thisVars: [ "this_h" ], + localVars: [] }, + body: + { body: "if(_inline_1_arg0_this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}", + args:[ + {name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2}, + {name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}], + thisVars:["this_i","this_v"], + localVars:["_inline_1_k"]}, + post:{ + body:"{return this_i}", + args:[], + thisVars:["this_i"], + localVars:[]} +}) + +exports.random = makeOp({ + args: ["array"], + pre: {args:[], body:"this_f=Math.random", thisVars:["this_f"]}, + body: {args: ["a"], body:"a=this_f()", thisVars:["this_f"]}, + funcName: "random" +}) + +exports.assign = makeOp({ + args:["array", "array"], + body: {args:["a", "b"], body:"a=b"}, + funcName: "assign" }) + +exports.assigns = makeOp({ + args:["array", "scalar"], + body: {args:["a", "b"], body:"a=b"}, + funcName: "assigns" }) + + +exports.equals = compile({ + args:["array", "array"], + pre: EmptyProc, + body: {args:[{name:"x", lvalue:false, rvalue:true, count:1}, + {name:"y", lvalue:false, rvalue:true, count:1}], + body: "if(x!==y){return false}", + localVars: [], + thisVars: []}, + post: {args:[], localVars:[], thisVars:[], body:"return true"}, + funcName: "equals" +}) + + + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + +module.exports = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports) { + +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self + // eslint-disable-next-line no-new-func + : Function('return this')(); +if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(5); +module.exports = function (it) { + if (!isObject(it)) throw TypeError(it + ' is not an object!'); + return it; +}; + + +/***/ }), +/* 8 */ +/***/ (function(module, exports) { + +module.exports = function (exec) { + try { + return !!exec(); + } catch (e) { + return true; + } +}; + + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +var store = __webpack_require__(89)('wks'); +var uid = __webpack_require__(34); +var Symbol = __webpack_require__(6).Symbol; +var USE_SYMBOL = typeof Symbol == 'function'; + +var $exports = module.exports = function (name) { + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); +}; + +$exports.store = store; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +var anObject = __webpack_require__(7); +var IE8_DOM_DEFINE = __webpack_require__(116); +var toPrimitive = __webpack_require__(54); +var dP = Object.defineProperty; + +exports.f = __webpack_require__(13) ? Object.defineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if (IE8_DOM_DEFINE) try { + return dP(O, P, Attributes); + } catch (e) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; +}; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var parse = __webpack_require__(420) +var compile = __webpack_require__(165) + +var REQUIRED_FIELDS = [ "args", "body" ] +var OPTIONAL_FIELDS = [ "pre", "post", "printCode", "funcName", "blockSize" ] + +function createCWise(user_args) { + //Check parameters + for(var id in user_args) { + if(REQUIRED_FIELDS.indexOf(id) < 0 && + OPTIONAL_FIELDS.indexOf(id) < 0) { + console.warn("cwise: Unknown argument '"+id+"' passed to expression compiler") + } + } + for(var i=0; i 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 +}; + + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +// Thank's IE8 for his funny defineProperty +module.exports = !__webpack_require__(8)(function () { + return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; +}); + + +/***/ }), +/* 14 */ +/***/ (function(module, exports) { + +var hasOwnProperty = {}.hasOwnProperty; +module.exports = function (it, key) { + return hasOwnProperty.call(it, key); +}; + + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var bind = __webpack_require__(159); +var isBuffer = __webpack_require__(160); + +/*global toString:true*/ + +// utils is a library of generic helper functions non-specific to axios + +var toString = Object.prototype.toString; + +/** + * Determine if a value is an Array + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Array, otherwise false + */ +function isArray(val) { + return toString.call(val) === '[object Array]'; +} + +/** + * Determine if a value is an ArrayBuffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an ArrayBuffer, otherwise false + */ +function isArrayBuffer(val) { + return toString.call(val) === '[object ArrayBuffer]'; +} + +/** + * Determine if a value is a FormData + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an FormData, otherwise false + */ +function isFormData(val) { + return (typeof FormData !== 'undefined') && (val instanceof FormData); +} + +/** + * Determine if a value is a view on an ArrayBuffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false + */ +function isArrayBufferView(val) { + var result; + if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { + result = ArrayBuffer.isView(val); + } else { + result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); + } + return result; +} + +/** + * Determine if a value is a String + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a String, otherwise false + */ +function isString(val) { + return typeof val === 'string'; +} + +/** + * Determine if a value is a Number + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Number, otherwise false + */ +function isNumber(val) { + return typeof val === 'number'; +} + +/** + * Determine if a value is undefined + * + * @param {Object} val The value to test + * @returns {boolean} True if the value is undefined, otherwise false + */ +function isUndefined(val) { + return typeof val === 'undefined'; +} + +/** + * Determine if a value is an Object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Object, otherwise false + */ +function isObject(val) { + return val !== null && typeof val === 'object'; +} + +/** + * Determine if a value is a Date + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Date, otherwise false + */ +function isDate(val) { + return toString.call(val) === '[object Date]'; +} + +/** + * Determine if a value is a File + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a File, otherwise false + */ +function isFile(val) { + return toString.call(val) === '[object File]'; +} + +/** + * Determine if a value is a Blob + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Blob, otherwise false + */ +function isBlob(val) { + return toString.call(val) === '[object Blob]'; +} + +/** + * Determine if a value is a Function + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Function, otherwise false + */ +function isFunction(val) { + return toString.call(val) === '[object Function]'; +} + +/** + * Determine if a value is a Stream + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Stream, otherwise false + */ +function isStream(val) { + return isObject(val) && isFunction(val.pipe); +} + +/** + * Determine if a value is a URLSearchParams object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a URLSearchParams object, otherwise false + */ +function isURLSearchParams(val) { + return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; +} + +/** + * Trim excess whitespace off the beginning and end of a string + * + * @param {String} str The String to trim + * @returns {String} The String freed of excess whitespace + */ +function trim(str) { + return str.replace(/^\s*/, '').replace(/\s*$/, ''); +} + +/** + * Determine if we're running in a standard browser environment + * + * This allows axios to run in a web worker, and react-native. + * Both environments support XMLHttpRequest, but not fully standard globals. + * + * web workers: + * typeof window -> undefined + * typeof document -> undefined + * + * react-native: + * navigator.product -> 'ReactNative' + */ +function isStandardBrowserEnv() { + if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { + return false; + } + return ( + typeof window !== 'undefined' && + typeof document !== 'undefined' + ); +} + +/** + * Iterate over an Array or an Object invoking a function for each item. + * + * If `obj` is an Array callback will be called passing + * the value, index, and complete array for each item. + * + * If 'obj' is an Object callback will be called passing + * the value, key, and complete object for each property. + * + * @param {Object|Array} obj The object to iterate + * @param {Function} fn The callback to invoke for each item + */ +function forEach(obj, fn) { + // Don't bother if no value provided + if (obj === null || typeof obj === 'undefined') { + return; + } + + // Force an array if not already something iterable + if (typeof obj !== 'object') { + /*eslint no-param-reassign:0*/ + obj = [obj]; + } + + if (isArray(obj)) { + // Iterate over array values + for (var i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj); + } + } else { + // Iterate over object keys + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + fn.call(null, obj[key], key, obj); + } + } + } +} + +/** + * Accepts varargs expecting each argument to be an object, then + * immutably merges the properties of each object and returns result. + * + * When multiple objects contain the same key the later object in + * the arguments list will take precedence. + * + * Example: + * + * ```js + * var result = merge({foo: 123}, {foo: 456}); + * console.log(result.foo); // outputs 456 + * ``` + * + * @param {Object} obj1 Object to merge + * @returns {Object} Result of all merge properties + */ +function merge(/* obj1, obj2, obj3, ... */) { + var result = {}; + function assignValue(val, key) { + if (typeof result[key] === 'object' && typeof val === 'object') { + result[key] = merge(result[key], val); + } else { + result[key] = val; + } + } + + for (var i = 0, l = arguments.length; i < l; i++) { + forEach(arguments[i], assignValue); + } + return result; +} + +/** + * Extends object a by mutably adding to it the properties of object b. + * + * @param {Object} a The object to be extended + * @param {Object} b The object to copy properties from + * @param {Object} thisArg The object to bind function to + * @return {Object} The resulting value of object a + */ +function extend(a, b, thisArg) { + forEach(b, function assignValue(val, key) { + if (thisArg && typeof val === 'function') { + a[key] = bind(val, thisArg); + } else { + a[key] = val; + } + }); + return a; +} + +module.exports = { + isArray: isArray, + isArrayBuffer: isArrayBuffer, + isBuffer: isBuffer, + isFormData: isFormData, + isArrayBufferView: isArrayBufferView, + isString: isString, + isNumber: isNumber, + isObject: isObject, + isUndefined: isUndefined, + isDate: isDate, + isFile: isFile, + isBlob: isBlob, + isFunction: isFunction, + isStream: isStream, + isURLSearchParams: isURLSearchParams, + isStandardBrowserEnv: isStandardBrowserEnv, + forEach: forEach, + merge: merge, + extend: extend, + trim: trim +}; + + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + +var dP = __webpack_require__(10); +var createDesc = __webpack_require__(33); +module.exports = __webpack_require__(13) ? function (object, key, value) { + return dP.f(object, key, createDesc(1, value)); +} : function (object, key, value) { + object[key] = value; + return object; +}; + + +/***/ }), +/* 17 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +module.exports = isArray; + + +/***/ }), +/* 18 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__softmax__ = __webpack_require__(418); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__elu__ = __webpack_require__(419); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__selu__ = __webpack_require__(422); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__softplus__ = __webpack_require__(423); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__softsign__ = __webpack_require__(424); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__relu__ = __webpack_require__(425); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__tanh__ = __webpack_require__(426); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__sigmoid__ = __webpack_require__(427); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__hard_sigmoid__ = __webpack_require__(428); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__linear__ = __webpack_require__(429); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "softmax", function() { return __WEBPACK_IMPORTED_MODULE_0__softmax__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "elu", function() { return __WEBPACK_IMPORTED_MODULE_1__elu__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "selu", function() { return __WEBPACK_IMPORTED_MODULE_2__selu__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "softplus", function() { return __WEBPACK_IMPORTED_MODULE_3__softplus__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "softsign", function() { return __WEBPACK_IMPORTED_MODULE_4__softsign__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "relu", function() { return __WEBPACK_IMPORTED_MODULE_5__relu__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "tanh", function() { return __WEBPACK_IMPORTED_MODULE_6__tanh__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "sigmoid", function() { return __WEBPACK_IMPORTED_MODULE_7__sigmoid__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "hard_sigmoid", function() { return __WEBPACK_IMPORTED_MODULE_8__hard_sigmoid__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "linear", function() { return __WEBPACK_IMPORTED_MODULE_9__linear__["a"]; }); + + + + + + + + + + + + +/***/ }), +/* 19 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = createGLSLProgram; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__merge_add__ = __webpack_require__(435); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__merge_average__ = __webpack_require__(436); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__merge_concatenate__ = __webpack_require__(437); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__merge_maximum__ = __webpack_require__(441); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__merge_minimum__ = __webpack_require__(442); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__merge_multiply__ = __webpack_require__(443); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__merge_subtract__ = __webpack_require__(444); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__convolutional_conv2d__ = __webpack_require__(445); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__convolutional_conv2dTranspose__ = __webpack_require__(446); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__visualizations_cam__ = __webpack_require__(447); + + + + + + + + + + +function createGLSLProgram(program) { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + switch (program) { + case 'add': + return __WEBPACK_IMPORTED_MODULE_0__merge_add__["a" /* default */].apply(void 0, args); + + case 'average': + return __WEBPACK_IMPORTED_MODULE_1__merge_average__["a" /* default */].apply(void 0, args); + + case 'concatenate': + return __WEBPACK_IMPORTED_MODULE_2__merge_concatenate__["a" /* default */].apply(void 0, args); + + case 'maximum': + return __WEBPACK_IMPORTED_MODULE_3__merge_maximum__["a" /* default */].apply(void 0, args); + + case 'minimum': + return __WEBPACK_IMPORTED_MODULE_4__merge_minimum__["a" /* default */].apply(void 0, args); + + case 'multiply': + return __WEBPACK_IMPORTED_MODULE_5__merge_multiply__["a" /* default */].apply(void 0, args); + + case 'subtract': + return __WEBPACK_IMPORTED_MODULE_6__merge_subtract__["a" /* default */].apply(void 0, args); + + case 'conv2d': + return __WEBPACK_IMPORTED_MODULE_7__convolutional_conv2d__["a" /* default */].apply(void 0, args); + + case 'conv2dTranspose': + return __WEBPACK_IMPORTED_MODULE_8__convolutional_conv2dTranspose__["a" /* default */].apply(void 0, args); + + case 'cam': + return __WEBPACK_IMPORTED_MODULE_9__visualizations_cam__["a" /* default */].apply(void 0, args); + + default: + throw new Error('GLSL program not found'); + } +} + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + +// to indexed object, toObject with fallback for non-array-like ES3 strings +var IObject = __webpack_require__(86); +var defined = __webpack_require__(30); +module.exports = function (it) { + return IObject(defined(it)); +}; + + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +// most Object methods by ES6 should accept primitives +var $export = __webpack_require__(0); +var core = __webpack_require__(41); +var fails = __webpack_require__(8); +module.exports = function (KEY, exec) { + var fn = (core.Object || {})[KEY] || Object[KEY]; + var exp = {}; + exp[KEY] = exec(fn); + $export($export.S + $export.F * fails(function () { fn(1); }), 'Object', exp); +}; + + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + +var freeGlobal = __webpack_require__(141); + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +module.exports = root; + + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __webpack_require__) { + +// optional / simple context binding +var aFunction = __webpack_require__(35); +module.exports = function (fn, that, length) { + aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; +}; + + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.1.13 ToObject(argument) +var defined = __webpack_require__(30); +module.exports = function (it) { + return Object(defined(it)); +}; + + +/***/ }), +/* 25 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +if (__webpack_require__(13)) { + var LIBRARY = __webpack_require__(42); + var global = __webpack_require__(6); + var fails = __webpack_require__(8); + var $export = __webpack_require__(0); + var $typed = __webpack_require__(85); + var $buffer = __webpack_require__(117); + var ctx = __webpack_require__(23); + var anInstance = __webpack_require__(44); + var propertyDesc = __webpack_require__(33); + var hide = __webpack_require__(16); + var redefineAll = __webpack_require__(43); + var toInteger = __webpack_require__(36); + var toLength = __webpack_require__(12); + var toIndex = __webpack_require__(118); + var toAbsoluteIndex = __webpack_require__(46); + var toPrimitive = __webpack_require__(54); + var has = __webpack_require__(14); + var classof = __webpack_require__(93); + var isObject = __webpack_require__(5); + var toObject = __webpack_require__(24); + var isArrayIter = __webpack_require__(94); + var create = __webpack_require__(56); + var getPrototypeOf = __webpack_require__(49); + var gOPN = __webpack_require__(55).f; + var getIterFn = __webpack_require__(95); + var uid = __webpack_require__(34); + var wks = __webpack_require__(9); + var createArrayMethod = __webpack_require__(57); + var createArrayIncludes = __webpack_require__(87); + var speciesConstructor = __webpack_require__(92); + var ArrayIterators = __webpack_require__(96); + var Iterators = __webpack_require__(48); + var $iterDetect = __webpack_require__(69); + var setSpecies = __webpack_require__(68); + var arrayFill = __webpack_require__(91); + var arrayCopyWithin = __webpack_require__(124); + var $DP = __webpack_require__(10); + var $GOPD = __webpack_require__(26); + var dP = $DP.f; + var gOPD = $GOPD.f; + var RangeError = global.RangeError; + var TypeError = global.TypeError; + var Uint8Array = global.Uint8Array; + var ARRAY_BUFFER = 'ArrayBuffer'; + var SHARED_BUFFER = 'Shared' + ARRAY_BUFFER; + var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT'; + var PROTOTYPE = 'prototype'; + var ArrayProto = Array[PROTOTYPE]; + var $ArrayBuffer = $buffer.ArrayBuffer; + var $DataView = $buffer.DataView; + var arrayForEach = createArrayMethod(0); + var arrayFilter = createArrayMethod(2); + var arraySome = createArrayMethod(3); + var arrayEvery = createArrayMethod(4); + var arrayFind = createArrayMethod(5); + var arrayFindIndex = createArrayMethod(6); + var arrayIncludes = createArrayIncludes(true); + var arrayIndexOf = createArrayIncludes(false); + var arrayValues = ArrayIterators.values; + var arrayKeys = ArrayIterators.keys; + var arrayEntries = ArrayIterators.entries; + var arrayLastIndexOf = ArrayProto.lastIndexOf; + var arrayReduce = ArrayProto.reduce; + var arrayReduceRight = ArrayProto.reduceRight; + var arrayJoin = ArrayProto.join; + var arraySort = ArrayProto.sort; + var arraySlice = ArrayProto.slice; + var arrayToString = ArrayProto.toString; + var arrayToLocaleString = ArrayProto.toLocaleString; + var ITERATOR = wks('iterator'); + var TAG = wks('toStringTag'); + var TYPED_CONSTRUCTOR = uid('typed_constructor'); + var DEF_CONSTRUCTOR = uid('def_constructor'); + var ALL_CONSTRUCTORS = $typed.CONSTR; + var TYPED_ARRAY = $typed.TYPED; + var VIEW = $typed.VIEW; + var WRONG_LENGTH = 'Wrong length!'; + + var $map = createArrayMethod(1, function (O, length) { + return allocate(speciesConstructor(O, O[DEF_CONSTRUCTOR]), length); + }); + + var LITTLE_ENDIAN = fails(function () { + // eslint-disable-next-line no-undef + return new Uint8Array(new Uint16Array([1]).buffer)[0] === 1; + }); + + var FORCED_SET = !!Uint8Array && !!Uint8Array[PROTOTYPE].set && fails(function () { + new Uint8Array(1).set({}); + }); + + var toOffset = function (it, BYTES) { + var offset = toInteger(it); + if (offset < 0 || offset % BYTES) throw RangeError('Wrong offset!'); + return offset; + }; + + var validate = function (it) { + if (isObject(it) && TYPED_ARRAY in it) return it; + throw TypeError(it + ' is not a typed array!'); + }; + + var allocate = function (C, length) { + if (!(isObject(C) && TYPED_CONSTRUCTOR in C)) { + throw TypeError('It is not a typed array constructor!'); + } return new C(length); + }; + + var speciesFromList = function (O, list) { + return fromList(speciesConstructor(O, O[DEF_CONSTRUCTOR]), list); + }; + + var fromList = function (C, list) { + var index = 0; + var length = list.length; + var result = allocate(C, length); + while (length > index) result[index] = list[index++]; + return result; + }; + + var addGetter = function (it, key, internal) { + dP(it, key, { get: function () { return this._d[internal]; } }); + }; + + var $from = function from(source /* , mapfn, thisArg */) { + var O = toObject(source); + var aLen = arguments.length; + var mapfn = aLen > 1 ? arguments[1] : undefined; + var mapping = mapfn !== undefined; + var iterFn = getIterFn(O); + var i, length, values, result, step, iterator; + if (iterFn != undefined && !isArrayIter(iterFn)) { + for (iterator = iterFn.call(O), values = [], i = 0; !(step = iterator.next()).done; i++) { + values.push(step.value); + } O = values; + } + if (mapping && aLen > 2) mapfn = ctx(mapfn, arguments[2], 2); + for (i = 0, length = toLength(O.length), result = allocate(this, length); length > i; i++) { + result[i] = mapping ? mapfn(O[i], i) : O[i]; + } + return result; + }; + + var $of = function of(/* ...items */) { + var index = 0; + var length = arguments.length; + var result = allocate(this, length); + while (length > index) result[index] = arguments[index++]; + return result; + }; + + // iOS Safari 6.x fails here + var TO_LOCALE_BUG = !!Uint8Array && fails(function () { arrayToLocaleString.call(new Uint8Array(1)); }); + + var $toLocaleString = function toLocaleString() { + return arrayToLocaleString.apply(TO_LOCALE_BUG ? arraySlice.call(validate(this)) : validate(this), arguments); + }; + + var proto = { + copyWithin: function copyWithin(target, start /* , end */) { + return arrayCopyWithin.call(validate(this), target, start, arguments.length > 2 ? arguments[2] : undefined); + }, + every: function every(callbackfn /* , thisArg */) { + return arrayEvery(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); + }, + fill: function fill(value /* , start, end */) { // eslint-disable-line no-unused-vars + return arrayFill.apply(validate(this), arguments); + }, + filter: function filter(callbackfn /* , thisArg */) { + return speciesFromList(this, arrayFilter(validate(this), callbackfn, + arguments.length > 1 ? arguments[1] : undefined)); + }, + find: function find(predicate /* , thisArg */) { + return arrayFind(validate(this), predicate, arguments.length > 1 ? arguments[1] : undefined); + }, + findIndex: function findIndex(predicate /* , thisArg */) { + return arrayFindIndex(validate(this), predicate, arguments.length > 1 ? arguments[1] : undefined); + }, + forEach: function forEach(callbackfn /* , thisArg */) { + arrayForEach(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); + }, + indexOf: function indexOf(searchElement /* , fromIndex */) { + return arrayIndexOf(validate(this), searchElement, arguments.length > 1 ? arguments[1] : undefined); + }, + includes: function includes(searchElement /* , fromIndex */) { + return arrayIncludes(validate(this), searchElement, arguments.length > 1 ? arguments[1] : undefined); + }, + join: function join(separator) { // eslint-disable-line no-unused-vars + return arrayJoin.apply(validate(this), arguments); + }, + lastIndexOf: function lastIndexOf(searchElement /* , fromIndex */) { // eslint-disable-line no-unused-vars + return arrayLastIndexOf.apply(validate(this), arguments); + }, + map: function map(mapfn /* , thisArg */) { + return $map(validate(this), mapfn, arguments.length > 1 ? arguments[1] : undefined); + }, + reduce: function reduce(callbackfn /* , initialValue */) { // eslint-disable-line no-unused-vars + return arrayReduce.apply(validate(this), arguments); + }, + reduceRight: function reduceRight(callbackfn /* , initialValue */) { // eslint-disable-line no-unused-vars + return arrayReduceRight.apply(validate(this), arguments); + }, + reverse: function reverse() { + var that = this; + var length = validate(that).length; + var middle = Math.floor(length / 2); + var index = 0; + var value; + while (index < middle) { + value = that[index]; + that[index++] = that[--length]; + that[length] = value; + } return that; + }, + some: function some(callbackfn /* , thisArg */) { + return arraySome(validate(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined); + }, + sort: function sort(comparefn) { + return arraySort.call(validate(this), comparefn); + }, + subarray: function subarray(begin, end) { + var O = validate(this); + var length = O.length; + var $begin = toAbsoluteIndex(begin, length); + return new (speciesConstructor(O, O[DEF_CONSTRUCTOR]))( + O.buffer, + O.byteOffset + $begin * O.BYTES_PER_ELEMENT, + toLength((end === undefined ? length : toAbsoluteIndex(end, length)) - $begin) + ); + } + }; + + var $slice = function slice(start, end) { + return speciesFromList(this, arraySlice.call(validate(this), start, end)); + }; + + var $set = function set(arrayLike /* , offset */) { + validate(this); + var offset = toOffset(arguments[1], 1); + var length = this.length; + var src = toObject(arrayLike); + var len = toLength(src.length); + var index = 0; + if (len + offset > length) throw RangeError(WRONG_LENGTH); + while (index < len) this[offset + index] = src[index++]; + }; + + var $iterators = { + entries: function entries() { + return arrayEntries.call(validate(this)); + }, + keys: function keys() { + return arrayKeys.call(validate(this)); + }, + values: function values() { + return arrayValues.call(validate(this)); + } + }; + + var isTAIndex = function (target, key) { + return isObject(target) + && target[TYPED_ARRAY] + && typeof key != 'symbol' + && key in target + && String(+key) == String(key); + }; + var $getDesc = function getOwnPropertyDescriptor(target, key) { + return isTAIndex(target, key = toPrimitive(key, true)) + ? propertyDesc(2, target[key]) + : gOPD(target, key); + }; + var $setDesc = function defineProperty(target, key, desc) { + if (isTAIndex(target, key = toPrimitive(key, true)) + && isObject(desc) + && has(desc, 'value') + && !has(desc, 'get') + && !has(desc, 'set') + // TODO: add validation descriptor w/o calling accessors + && !desc.configurable + && (!has(desc, 'writable') || desc.writable) + && (!has(desc, 'enumerable') || desc.enumerable) + ) { + target[key] = desc.value; + return target; + } return dP(target, key, desc); + }; + + if (!ALL_CONSTRUCTORS) { + $GOPD.f = $getDesc; + $DP.f = $setDesc; + } + + $export($export.S + $export.F * !ALL_CONSTRUCTORS, 'Object', { + getOwnPropertyDescriptor: $getDesc, + defineProperty: $setDesc + }); + + if (fails(function () { arrayToString.call({}); })) { + arrayToString = arrayToLocaleString = function toString() { + return arrayJoin.call(this); + }; + } + + var $TypedArrayPrototype$ = redefineAll({}, proto); + redefineAll($TypedArrayPrototype$, $iterators); + hide($TypedArrayPrototype$, ITERATOR, $iterators.values); + redefineAll($TypedArrayPrototype$, { + slice: $slice, + set: $set, + constructor: function () { /* noop */ }, + toString: arrayToString, + toLocaleString: $toLocaleString + }); + addGetter($TypedArrayPrototype$, 'buffer', 'b'); + addGetter($TypedArrayPrototype$, 'byteOffset', 'o'); + addGetter($TypedArrayPrototype$, 'byteLength', 'l'); + addGetter($TypedArrayPrototype$, 'length', 'e'); + dP($TypedArrayPrototype$, TAG, { + get: function () { return this[TYPED_ARRAY]; } + }); + + // eslint-disable-next-line max-statements + module.exports = function (KEY, BYTES, wrapper, CLAMPED) { + CLAMPED = !!CLAMPED; + var NAME = KEY + (CLAMPED ? 'Clamped' : '') + 'Array'; + var GETTER = 'get' + KEY; + var SETTER = 'set' + KEY; + var TypedArray = global[NAME]; + var Base = TypedArray || {}; + var TAC = TypedArray && getPrototypeOf(TypedArray); + var FORCED = !TypedArray || !$typed.ABV; + var O = {}; + var TypedArrayPrototype = TypedArray && TypedArray[PROTOTYPE]; + var getter = function (that, index) { + var data = that._d; + return data.v[GETTER](index * BYTES + data.o, LITTLE_ENDIAN); + }; + var setter = function (that, index, value) { + var data = that._d; + if (CLAMPED) value = (value = Math.round(value)) < 0 ? 0 : value > 0xff ? 0xff : value & 0xff; + data.v[SETTER](index * BYTES + data.o, value, LITTLE_ENDIAN); + }; + var addElement = function (that, index) { + dP(that, index, { + get: function () { + return getter(this, index); + }, + set: function (value) { + return setter(this, index, value); + }, + enumerable: true + }); + }; + if (FORCED) { + TypedArray = wrapper(function (that, data, $offset, $length) { + anInstance(that, TypedArray, NAME, '_d'); + var index = 0; + var offset = 0; + var buffer, byteLength, length, klass; + if (!isObject(data)) { + length = toIndex(data); + byteLength = length * BYTES; + buffer = new $ArrayBuffer(byteLength); + } else if (data instanceof $ArrayBuffer || (klass = classof(data)) == ARRAY_BUFFER || klass == SHARED_BUFFER) { + buffer = data; + offset = toOffset($offset, BYTES); + var $len = data.byteLength; + if ($length === undefined) { + if ($len % BYTES) throw RangeError(WRONG_LENGTH); + byteLength = $len - offset; + if (byteLength < 0) throw RangeError(WRONG_LENGTH); + } else { + byteLength = toLength($length) * BYTES; + if (byteLength + offset > $len) throw RangeError(WRONG_LENGTH); + } + length = byteLength / BYTES; + } else if (TYPED_ARRAY in data) { + return fromList(TypedArray, data); + } else { + return $from.call(TypedArray, data); + } + hide(that, '_d', { + b: buffer, + o: offset, + l: byteLength, + e: length, + v: new $DataView(buffer) + }); + while (index < length) addElement(that, index++); + }); + TypedArrayPrototype = TypedArray[PROTOTYPE] = create($TypedArrayPrototype$); + hide(TypedArrayPrototype, 'constructor', TypedArray); + } else if (!fails(function () { + TypedArray(1); + }) || !fails(function () { + new TypedArray(-1); // eslint-disable-line no-new + }) || !$iterDetect(function (iter) { + new TypedArray(); // eslint-disable-line no-new + new TypedArray(null); // eslint-disable-line no-new + new TypedArray(1.5); // eslint-disable-line no-new + new TypedArray(iter); // eslint-disable-line no-new + }, true)) { + TypedArray = wrapper(function (that, data, $offset, $length) { + anInstance(that, TypedArray, NAME); + var klass; + // `ws` module bug, temporarily remove validation length for Uint8Array + // https://github.com/websockets/ws/pull/645 + if (!isObject(data)) return new Base(toIndex(data)); + if (data instanceof $ArrayBuffer || (klass = classof(data)) == ARRAY_BUFFER || klass == SHARED_BUFFER) { + return $length !== undefined + ? new Base(data, toOffset($offset, BYTES), $length) + : $offset !== undefined + ? new Base(data, toOffset($offset, BYTES)) + : new Base(data); + } + if (TYPED_ARRAY in data) return fromList(TypedArray, data); + return $from.call(TypedArray, data); + }); + arrayForEach(TAC !== Function.prototype ? gOPN(Base).concat(gOPN(TAC)) : gOPN(Base), function (key) { + if (!(key in TypedArray)) hide(TypedArray, key, Base[key]); + }); + TypedArray[PROTOTYPE] = TypedArrayPrototype; + if (!LIBRARY) TypedArrayPrototype.constructor = TypedArray; + } + var $nativeIterator = TypedArrayPrototype[ITERATOR]; + var CORRECT_ITER_NAME = !!$nativeIterator + && ($nativeIterator.name == 'values' || $nativeIterator.name == undefined); + var $iterator = $iterators.values; + hide(TypedArray, TYPED_CONSTRUCTOR, true); + hide(TypedArrayPrototype, TYPED_ARRAY, NAME); + hide(TypedArrayPrototype, VIEW, true); + hide(TypedArrayPrototype, DEF_CONSTRUCTOR, TypedArray); + + if (CLAMPED ? new TypedArray(1)[TAG] != NAME : !(TAG in TypedArrayPrototype)) { + dP(TypedArrayPrototype, TAG, { + get: function () { return NAME; } + }); + } + + O[NAME] = TypedArray; + + $export($export.G + $export.W + $export.F * (TypedArray != Base), O); + + $export($export.S, NAME, { + BYTES_PER_ELEMENT: BYTES + }); + + $export($export.S + $export.F * fails(function () { Base.of.call(TypedArray, 1); }), NAME, { + from: $from, + of: $of + }); + + if (!(BYTES_PER_ELEMENT in TypedArrayPrototype)) hide(TypedArrayPrototype, BYTES_PER_ELEMENT, BYTES); + + $export($export.P, NAME, proto); + + setSpecies(NAME); + + $export($export.P + $export.F * FORCED_SET, NAME, { set: $set }); + + $export($export.P + $export.F * !CORRECT_ITER_NAME, NAME, $iterators); + + if (!LIBRARY && TypedArrayPrototype.toString != arrayToString) TypedArrayPrototype.toString = arrayToString; + + $export($export.P + $export.F * fails(function () { + new TypedArray(1).slice(); + }), NAME, { slice: $slice }); + + $export($export.P + $export.F * (fails(function () { + return [1, 2].toLocaleString() != new TypedArray([1, 2]).toLocaleString(); + }) || !fails(function () { + TypedArrayPrototype.toLocaleString.call([1, 2]); + })), NAME, { toLocaleString: $toLocaleString }); + + Iterators[NAME] = CORRECT_ITER_NAME ? $nativeIterator : $iterator; + if (!LIBRARY && !CORRECT_ITER_NAME) hide(TypedArrayPrototype, ITERATOR, $iterator); + }; +} else module.exports = function () { /* empty */ }; + + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __webpack_require__) { + +var pIE = __webpack_require__(58); +var createDesc = __webpack_require__(33); +var toIObject = __webpack_require__(20); +var toPrimitive = __webpack_require__(54); +var has = __webpack_require__(14); +var IE8_DOM_DEFINE = __webpack_require__(116); +var gOPD = Object.getOwnPropertyDescriptor; + +exports.f = __webpack_require__(13) ? gOPD : function getOwnPropertyDescriptor(O, P) { + O = toIObject(O); + P = toPrimitive(P, true); + if (IE8_DOM_DEFINE) try { + return gOPD(O, P); + } catch (e) { /* empty */ } + if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]); +}; + + +/***/ }), +/* 27 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = checkShape; +/* harmony export (immutable) */ __webpack_exports__["c"] = data3DLayoutForGL; +/* harmony export (immutable) */ __webpack_exports__["b"] = createIndicesFor2DReshaped; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_range__ = __webpack_require__(39); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_range___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_range__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_ndarray__ = __webpack_require__(66); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_ndarray___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_ndarray__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_ndarray_ops__); + + +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + + + +function checkShape(data, shape) { + if (data.length && shape.length && data.length !== shape.reduce(function (a, b) { + return a * b; + }, 1)) { + throw new Error('[Tensor] specified shape incompatible with data.'); + } +} +function data3DLayoutForGL(typedarrayConstructor, arr, shape) { + var data = new typedarrayConstructor(arr.data.length); + var slice = __WEBPACK_IMPORTED_MODULE_1_ndarray___default()(new typedarrayConstructor(shape[0] * shape[1]), [shape[0], shape[1]]); + var offset = 0; + + for (var i = 0; i < shape[2]; i++) { + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.assign(slice, arr.pick(null, null, i)); + data.set(slice.data, offset); + offset += shape[0] * shape[1]; + } + + return data; +} +function createIndicesFor2DReshaped(shape) { + var square = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var axis = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1; + var size = shape.reduce(function (a, b) { + return a * b; + }, 1); + var indicesArr = __WEBPACK_IMPORTED_MODULE_1_ndarray___default()(new Int32Array(size), shape); + + if (square) { + var squareDim = Math.ceil(Math.sqrt(size)); + var indicesRowArrReshaped = __WEBPACK_IMPORTED_MODULE_1_ndarray___default()(new Int32Array(Math.pow(squareDim, 2)), [squareDim, squareDim]); + var indicesColArrReshaped = __WEBPACK_IMPORTED_MODULE_1_ndarray___default()(new Int32Array(Math.pow(squareDim, 2)), [squareDim, squareDim]); + var indicesArrReshaped = __WEBPACK_IMPORTED_MODULE_1_ndarray___default()(new Int32Array(Math.pow(squareDim, 2)), [squareDim, squareDim]); + + for (var i = 0; i < squareDim; i++) { + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.assigns(indicesRowArrReshaped.pick(i, null), i); + } + + for (var j = 0; j < squareDim; j++) { + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.assigns(indicesColArrReshaped.pick(null, j), j); + } + + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.muls(indicesArrReshaped, indicesRowArrReshaped, squareDim); + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.addeq(indicesArrReshaped, indicesColArrReshaped); + indicesArr.data.set(indicesArrReshaped.data.subarray(0, indicesArr.size)); + } else { + if (axis < 0) { + axis = shape.length + axis; + } + + var axisSize = shape[axis]; + var indicesRowArr = __WEBPACK_IMPORTED_MODULE_1_ndarray___default()(new Int32Array(size), shape); + var indicesColArr = __WEBPACK_IMPORTED_MODULE_1_ndarray___default()(new Int32Array(size), shape); + + var otherAxes = _toConsumableArray(shape.slice(0, axis)).concat(_toConsumableArray(shape.slice(axis + 1))); + + var otherAxesSize = otherAxes.reduce(function (a, b) { + return a * b; + }, 1); + var indicesRowArrSlice = __WEBPACK_IMPORTED_MODULE_1_ndarray___default()(new Int32Array(__WEBPACK_IMPORTED_MODULE_0_lodash_range___default()(otherAxesSize)), otherAxes); + var axisSlices = Array(shape.length).fill(null); + + for (var n = 0; n < axisSize; n++) { + axisSlices[axis] = n; + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.assign(indicesRowArr.pick.apply(indicesRowArr, _toConsumableArray(axisSlices)), indicesRowArrSlice); + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.assigns(indicesColArr.pick.apply(indicesColArr, _toConsumableArray(axisSlices)), n); + } + + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.muls(indicesArr, indicesRowArr, axisSize); + __WEBPACK_IMPORTED_MODULE_2_ndarray_ops___default.a.addeq(indicesArr, indicesColArr); + } + + return indicesArr; +} + +/***/ }), +/* 28 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "softmax", function() { return softmaxProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elu", function() { return eluProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "selu", function() { return seluProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "softplus", function() { return softplusProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "softsign", function() { return softsignProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "relu", function() { return reluProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tanh", function() { return tanhProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sigmoid", function() { return sigmoidProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hard_sigmoid", function() { return hardSigmoidProgramSource; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "linear", function() { return linearProgramSource; }); +var softmaxProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n float maxval = 0.0;\r\n for (int i = 0; i < int(size[0]); ++i) {\r\n float val = texelFetch(x, ivec2(i, out_y), 0).r;\r\n if (i == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n\r\n float sum = 0.0;\r\n for (int i = 0; i < int(size[0]); ++i) {\r\n float val = texelFetch(x, ivec2(i, out_y), 0).r;\r\n sum += exp(val - maxval);\r\n }\r\n\r\n outColor = exp(texture(x, vec2(outTex.x, outTex.y)) - maxval) / sum;\r\n}\r\n"; +var eluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n float alpha = 1.0;\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0);\r\n}\r\n"; +var seluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n float alpha = 1.6732632423543772848170429916717;\r\n float scale = 1.0507009873554804934193349852946;\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = scale * (max(v, 0.0) + alpha * (exp(min(v, 0.0)) - 1.0));\r\n}\r\n"; +var softplusProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = log(1.0 + exp(texture(x, vec2(outTex.x, outTex.y))));\r\n}\r\n"; +var softsignProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n v /= 1.0 + abs(v);\r\n outColor = v;\r\n}\r\n"; +var reluProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = max(v, 0.0);\r\n}\r\n"; +var tanhProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n outColor = tanh(v);\r\n}\r\n"; +var sigmoidProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = 1.0 / (1.0 + exp(-1.0 * texture(x, vec2(outTex.x, outTex.y))));\r\n}\r\n"; +var hardSigmoidProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n vec4 v = texture(x, vec2(outTex.x, outTex.y));\r\n v = v * 0.2 + 0.5;\r\n v = max(v, 0.0);\r\n v = min(v, 1.0);\r\n outColor = v;\r\n}\r\n"; +var linearProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n outColor = texture(x, vec2(outTex.x, outTex.y));\r\n}\r\n"; + + + + + + + + + + + +/***/ }), +/* 29 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(6); +var hide = __webpack_require__(16); +var has = __webpack_require__(14); +var SRC = __webpack_require__(34)('src'); +var TO_STRING = 'toString'; +var $toString = Function[TO_STRING]; +var TPL = ('' + $toString).split(TO_STRING); + +__webpack_require__(41).inspectSource = function (it) { + return $toString.call(it); +}; + +(module.exports = function (O, key, val, safe) { + var isFunction = typeof val == 'function'; + if (isFunction) has(val, 'name') || hide(val, 'name', key); + if (O[key] === val) return; + if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); + if (O === global) { + O[key] = val; + } else if (!safe) { + delete O[key]; + hide(O, key, val); + } else if (O[key]) { + O[key] = val; + } else { + hide(O, key, val); + } +// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative +})(Function.prototype, TO_STRING, function toString() { + return typeof this == 'function' && this[SRC] || $toString.call(this); +}); + + +/***/ }), +/* 30 */ +/***/ (function(module, exports) { + +// 7.2.1 RequireObjectCoercible(argument) +module.exports = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; +}; + + +/***/ }), +/* 31 */ +/***/ (function(module, exports, __webpack_require__) { + +var META = __webpack_require__(34)('meta'); +var isObject = __webpack_require__(5); +var has = __webpack_require__(14); +var setDesc = __webpack_require__(10).f; +var id = 0; +var isExtensible = Object.isExtensible || function () { + return true; +}; +var FREEZE = !__webpack_require__(8)(function () { + return isExtensible(Object.preventExtensions({})); +}); +var setMeta = function (it) { + setDesc(it, META, { value: { + i: 'O' + ++id, // object ID + w: {} // weak collections IDs + } }); +}; +var fastKey = function (it, create) { + // return primitive with prefix + if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; + if (!has(it, META)) { + // can't set metadata to uncaught frozen object + if (!isExtensible(it)) return 'F'; + // not necessary to add metadata + if (!create) return 'E'; + // add missing metadata + setMeta(it); + // return object ID + } return it[META].i; +}; +var getWeak = function (it, create) { + if (!has(it, META)) { + // can't set metadata to uncaught frozen object + if (!isExtensible(it)) return true; + // not necessary to add metadata + if (!create) return false; + // add missing metadata + setMeta(it); + // return hash weak collections IDs + } return it[META].w; +}; +// add metadata on freeze-family methods calling +var onFreeze = function (it) { + if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it); + return it; +}; +var meta = module.exports = { + KEY: META, + NEED: false, + fastKey: fastKey, + getWeak: getWeak, + onFreeze: onFreeze +}; + + +/***/ }), +/* 32 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _Merge; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_range__ = __webpack_require__(39); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_range___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_range__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual__ = __webpack_require__(75); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isEqual__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__Layer__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__WebGL2__ = __webpack_require__(2); + + + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } 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 _Merge = function (_Layer) { + _inherits(_Merge, _Layer); + + function _Merge() { + var _this; + + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, _Merge); + + _this = _possibleConstructorReturn(this, (_Merge.__proto__ || Object.getPrototypeOf(_Merge)).call(this, attrs)); + _this.layerClass = '_Merge'; + _this.isMergeLayer = true; + return _this; + } + + _createClass(_Merge, [{ + key: "call", + value: function call(inputs) { + if (this.gpu) { + this._callGPU(inputs); + } else { + var valid = this._validateInputs(inputs); + + if (!valid) { + this.throwError('Invalid inputs to call method.'); + } + + this._callCPU(inputs); + } + + return this.output; + } + }, { + key: "_validateInputs", + value: function _validateInputs(inputs) { + var shapes = inputs.map(function (x) { + return x.tensor.shape.slice(); + }); + + if (['sum', 'diff', 'mul', 'ave', 'max', 'min'].indexOf(this.mode) > -1) { + if (!shapes.every(function (shape) { + return __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual___default()(shape, shapes[0]); + })) { + this.throwError("All input shapes must be the same for mode ".concat(this.mode, ".")); + } + } + + if (this.mode === 'dot') { + if (inputs.length !== 2) { + this.throwError("Exactly 2 inputs required for mode ".concat(this.mode, ".")); + } + + if (this.dotAxes[0] < 0) { + this.dotAxes[0] = shapes[0].length + this.dotAxes[0]; + } + + if (this.dotAxes[1] < 0) { + this.dotAxes[1] = shapes[1].length + this.dotAxes[1]; + } + + if (shapes[0][this.dotAxes[0]] !== shapes[1][this.dotAxes[1]]) { + this.throwError('Dimensions incompatibility using dot mode.'); + } + } else if (this.mode === 'concat') { + var nonConcatShapes = shapes.slice(); + + var _concatAxis = this.concatAxis < 0 ? nonConcatShapes[0].length + this.concatAxis : this.concatAxis; + + if (this.concatAxis === 0) _concatAxis = 0; + + __WEBPACK_IMPORTED_MODULE_0_lodash_range___default()(nonConcatShapes.length).forEach(function (i) { + nonConcatShapes[i].splice(_concatAxis, 1); + }); + + if (!nonConcatShapes.every(function (shape) { + return __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual___default()(shape, nonConcatShapes[0]); + })) { + this.throwError('In concat mode, all shapes must be the same except along the concat axis.'); + } + } + + return true; + } + }, { + key: "_callCPU", + value: function _callCPU() {} + }, { + key: "_callGPU", + value: function _callGPU(inputs) { + inputs.forEach(function (input) { + if (!input.glTexture && !input.glTextureFragments) { + input.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + }); + + if (!this.output) { + this.output = new __WEBPACK_IMPORTED_MODULE_3__Tensor__["a" /* default */]([], inputs[0].glTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + + if (inputs[0].is1D) { + this.output.is1D = inputs[0].is1D; + } else if (inputs[0].is2DReshaped || inputs[0].is2DSquareReshaped) { + if (inputs[0].is2DReshaped) { + this.output.is2DReshaped = inputs[0].is2DReshaped; + } else if (inputs[0].is2DSquareReshaped) { + this.output.is2DSquareReshaped = inputs[0].is2DSquareReshaped; + } + + this.output.originalShape = inputs[0].originalShape.slice(); + this.output.indicesForReshaped = inputs[0].indicesForReshaped; + } + } + + __WEBPACK_IMPORTED_MODULE_4__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.mergeProgram, + output: this.output, + inputs: inputs.map(function (input, i) { + return { + input: input, + name: "inputs[".concat(i, "]") + }; + }), + supportsTextureFragments: true + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + + if (this.output.is2DReshaped) { + this.output.reshapeFrom2D(); + } else if (this.output.is2DSquareReshaped) { + this.output.reshapeFrom2DSquare(); + } + } + } + }]); + + return _Merge; +}(__WEBPACK_IMPORTED_MODULE_2__Layer__["a" /* default */]); + + + +/***/ }), +/* 33 */ +/***/ (function(module, exports) { + +module.exports = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; +}; + + +/***/ }), +/* 34 */ +/***/ (function(module, exports) { + +var id = 0; +var px = Math.random(); +module.exports = function (key) { + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); +}; + + +/***/ }), +/* 35 */ +/***/ (function(module, exports) { + +module.exports = function (it) { + if (typeof it != 'function') throw TypeError(it + ' is not a function!'); + return it; +}; + + +/***/ }), +/* 36 */ +/***/ (function(module, exports) { + +// 7.1.4 ToInteger +var ceil = Math.ceil; +var floor = Math.floor; +module.exports = function (it) { + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); +}; + + +/***/ }), +/* 37 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.14 / 15.2.3.14 Object.keys(O) +var $keys = __webpack_require__(119); +var enumBugKeys = __webpack_require__(90); + +module.exports = Object.keys || function keys(O) { + return $keys(O, enumBugKeys); +}; + + +/***/ }), +/* 38 */ +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), +/* 39 */ +/***/ (function(module, exports, __webpack_require__) { + +var createRange = __webpack_require__(411); + +/** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to, but not including, `end`. A step of `-1` is used if a negative + * `start` is specified without an `end` or `step`. If `end` is not specified, + * it's set to `start` with `start` then set to `0`. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns the range of numbers. + * @see _.inRange, _.rangeRight + * @example + * + * _.range(4); + * // => [0, 1, 2, 3] + * + * _.range(-4); + * // => [0, -1, -2, -3] + * + * _.range(1, 5); + * // => [1, 2, 3, 4] + * + * _.range(0, 20, 5); + * // => [0, 5, 10, 15] + * + * _.range(0, -4, -1); + * // => [0, -1, -2, -3] + * + * _.range(1, 4, 0); + * // => [1, 1, 1] + * + * _.range(0); + * // => [] + */ +var range = createRange(); + +module.exports = range; + + +/***/ }), +/* 40 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) { +var util = exports; + +// used to return a Promise where callback is omitted +util.asPromise = __webpack_require__(546); + +// converts to / from base64 encoded strings +util.base64 = __webpack_require__(547); + +// base class of rpc.Service +util.EventEmitter = __webpack_require__(548); + +// float handling accross browsers +util.float = __webpack_require__(549); + +// requires modules optionally and hides the call from bundlers +util.inquire = __webpack_require__(550); + +// converts to / from utf8 encoded strings +util.utf8 = __webpack_require__(551); + +// provides a node-like buffer pool in the browser +util.pool = __webpack_require__(552); + +// utility to work with the low and high bits of a 64 bit value +util.LongBits = __webpack_require__(553); + +/** + * An immuable empty array. + * @memberof util + * @type {Array.<*>} + * @const + */ +util.emptyArray = Object.freeze ? Object.freeze([]) : /* istanbul ignore next */ []; // used on prototypes + +/** + * An immutable empty object. + * @type {Object} + * @const + */ +util.emptyObject = Object.freeze ? Object.freeze({}) : /* istanbul ignore next */ {}; // used on prototypes + +/** + * Whether running within node or not. + * @memberof util + * @type {boolean} + * @const + */ +util.isNode = Boolean(global.process && global.process.versions && global.process.versions.node); + +/** + * Tests if the specified value is an integer. + * @function + * @param {*} value Value to test + * @returns {boolean} `true` if the value is an integer + */ +util.isInteger = Number.isInteger || /* istanbul ignore next */ function isInteger(value) { + return typeof value === "number" && isFinite(value) && Math.floor(value) === value; +}; + +/** + * Tests if the specified value is a string. + * @param {*} value Value to test + * @returns {boolean} `true` if the value is a string + */ +util.isString = function isString(value) { + return typeof value === "string" || value instanceof String; +}; + +/** + * Tests if the specified value is a non-null object. + * @param {*} value Value to test + * @returns {boolean} `true` if the value is a non-null object + */ +util.isObject = function isObject(value) { + return value && typeof value === "object"; +}; + +/** + * Checks if a property on a message is considered to be present. + * This is an alias of {@link util.isSet}. + * @function + * @param {Object} obj Plain object or message instance + * @param {string} prop Property name + * @returns {boolean} `true` if considered to be present, otherwise `false` + */ +util.isset = + +/** + * Checks if a property on a message is considered to be present. + * @param {Object} obj Plain object or message instance + * @param {string} prop Property name + * @returns {boolean} `true` if considered to be present, otherwise `false` + */ +util.isSet = function isSet(obj, prop) { + var value = obj[prop]; + if (value != null && obj.hasOwnProperty(prop)) // eslint-disable-line eqeqeq, no-prototype-builtins + return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0; + return false; +}; + +/** + * Any compatible Buffer instance. + * This is a minimal stand-alone definition of a Buffer instance. The actual type is that exported by node's typings. + * @interface Buffer + * @extends Uint8Array + */ + +/** + * Node's Buffer class if available. + * @type {Constructor} + */ +util.Buffer = (function() { + try { + var Buffer = util.inquire("buffer").Buffer; + // refuse to use non-node buffers if not explicitly assigned (perf reasons): + return Buffer.prototype.utf8Write ? Buffer : /* istanbul ignore next */ null; + } catch (e) { + /* istanbul ignore next */ + return null; + } +})(); + +// Internal alias of or polyfull for Buffer.from. +util._Buffer_from = null; + +// Internal alias of or polyfill for Buffer.allocUnsafe. +util._Buffer_allocUnsafe = null; + +/** + * Creates a new buffer of whatever type supported by the environment. + * @param {number|number[]} [sizeOrArray=0] Buffer size or number array + * @returns {Uint8Array|Buffer} Buffer + */ +util.newBuffer = function newBuffer(sizeOrArray) { + /* istanbul ignore next */ + return typeof sizeOrArray === "number" + ? util.Buffer + ? util._Buffer_allocUnsafe(sizeOrArray) + : new util.Array(sizeOrArray) + : util.Buffer + ? util._Buffer_from(sizeOrArray) + : typeof Uint8Array === "undefined" + ? sizeOrArray + : new Uint8Array(sizeOrArray); +}; + +/** + * Array implementation used in the browser. `Uint8Array` if supported, otherwise `Array`. + * @type {Constructor} + */ +util.Array = typeof Uint8Array !== "undefined" ? Uint8Array /* istanbul ignore next */ : Array; + +/** + * Any compatible Long instance. + * This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js. + * @interface Long + * @property {number} low Low bits + * @property {number} high High bits + * @property {boolean} unsigned Whether unsigned or not + */ + +/** + * Long.js's Long class if available. + * @type {Constructor} + */ +util.Long = /* istanbul ignore next */ global.dcodeIO && /* istanbul ignore next */ global.dcodeIO.Long || util.inquire("long"); + +/** + * Regular expression used to verify 2 bit (`bool`) map keys. + * @type {RegExp} + * @const + */ +util.key2Re = /^true|false|0|1$/; + +/** + * Regular expression used to verify 32 bit (`int32` etc.) map keys. + * @type {RegExp} + * @const + */ +util.key32Re = /^-?(?:0|[1-9][0-9]*)$/; + +/** + * Regular expression used to verify 64 bit (`int64` etc.) map keys. + * @type {RegExp} + * @const + */ +util.key64Re = /^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/; + +/** + * Converts a number or long to an 8 characters long hash string. + * @param {Long|number} value Value to convert + * @returns {string} Hash + */ +util.longToHash = function longToHash(value) { + return value + ? util.LongBits.from(value).toHash() + : util.LongBits.zeroHash; +}; + +/** + * Converts an 8 characters long hash string to a long or number. + * @param {string} hash Hash + * @param {boolean} [unsigned=false] Whether unsigned or not + * @returns {Long|number} Original value + */ +util.longFromHash = function longFromHash(hash, unsigned) { + var bits = util.LongBits.fromHash(hash); + if (util.Long) + return util.Long.fromBits(bits.lo, bits.hi, unsigned); + return bits.toNumber(Boolean(unsigned)); +}; + +/** + * Merges the properties of the source object into the destination object. + * @memberof util + * @param {Object.} dst Destination object + * @param {Object.} src Source object + * @param {boolean} [ifNotSet=false] Merges only if the key is not already set + * @returns {Object.} Destination object + */ +function merge(dst, src, ifNotSet) { // used by converters + for (var keys = Object.keys(src), i = 0; i < keys.length; ++i) + if (dst[keys[i]] === undefined || !ifNotSet) + dst[keys[i]] = src[keys[i]]; + return dst; +} + +util.merge = merge; + +/** + * Converts the first character of a string to lower case. + * @param {string} str String to convert + * @returns {string} Converted string + */ +util.lcFirst = function lcFirst(str) { + return str.charAt(0).toLowerCase() + str.substring(1); +}; + +/** + * Creates a custom error constructor. + * @memberof util + * @param {string} name Error name + * @returns {Constructor} Custom error constructor + */ +function newError(name) { + + function CustomError(message, properties) { + + if (!(this instanceof CustomError)) + return new CustomError(message, properties); + + // Error.call(this, message); + // ^ just returns a new error instance because the ctor can be called as a function + + Object.defineProperty(this, "message", { get: function() { return message; } }); + + /* istanbul ignore next */ + if (Error.captureStackTrace) // node + Error.captureStackTrace(this, CustomError); + else + Object.defineProperty(this, "stack", { value: (new Error()).stack || "" }); + + if (properties) + merge(this, properties); + } + + (CustomError.prototype = Object.create(Error.prototype)).constructor = CustomError; + + Object.defineProperty(CustomError.prototype, "name", { get: function() { return name; } }); + + CustomError.prototype.toString = function toString() { + return this.name + ": " + this.message; + }; + + return CustomError; +} + +util.newError = newError; + +/** + * Constructs a new protocol error. + * @classdesc Error subclass indicating a protocol specifc error. + * @memberof util + * @extends Error + * @template T extends Message + * @constructor + * @param {string} message Error message + * @param {Object.} [properties] Additional properties + * @example + * try { + * MyMessage.decode(someBuffer); // throws if required fields are missing + * } catch (e) { + * if (e instanceof ProtocolError && e.instance) + * console.log("decoded so far: " + JSON.stringify(e.instance)); + * } + */ +util.ProtocolError = newError("ProtocolError"); + +/** + * So far decoded message instance. + * @name util.ProtocolError#instance + * @type {Message} + */ + +/** + * A OneOf getter as returned by {@link util.oneOfGetter}. + * @typedef OneOfGetter + * @type {function} + * @returns {string|undefined} Set field name, if any + */ + +/** + * Builds a getter for a oneof's present field name. + * @param {string[]} fieldNames Field names + * @returns {OneOfGetter} Unbound getter + */ +util.oneOfGetter = function getOneOf(fieldNames) { + var fieldMap = {}; + for (var i = 0; i < fieldNames.length; ++i) + fieldMap[fieldNames[i]] = 1; + + /** + * @returns {string|undefined} Set field name, if any + * @this Object + * @ignore + */ + return function() { // eslint-disable-line consistent-return + for (var keys = Object.keys(this), i = keys.length - 1; i > -1; --i) + if (fieldMap[keys[i]] === 1 && this[keys[i]] !== undefined && this[keys[i]] !== null) + return keys[i]; + }; +}; + +/** + * A OneOf setter as returned by {@link util.oneOfSetter}. + * @typedef OneOfSetter + * @type {function} + * @param {string|undefined} value Field name + * @returns {undefined} + */ + +/** + * Builds a setter for a oneof's present field name. + * @param {string[]} fieldNames Field names + * @returns {OneOfSetter} Unbound setter + */ +util.oneOfSetter = function setOneOf(fieldNames) { + + /** + * @param {string} name Field name + * @returns {undefined} + * @this Object + * @ignore + */ + return function(name) { + for (var i = 0; i < fieldNames.length; ++i) + if (fieldNames[i] !== name) + delete this[fieldNames[i]]; + }; +}; + +/** + * Default conversion options used for {@link Message#toJSON} implementations. + * + * These options are close to proto3's JSON mapping with the exception that internal types like Any are handled just like messages. More precisely: + * + * - Longs become strings + * - Enums become string keys + * - Bytes become base64 encoded strings + * - (Sub-)Messages become plain objects + * - Maps become plain objects with all string keys + * - Repeated fields become arrays + * - NaN and Infinity for float and double fields become strings + * + * @type {IConversionOptions} + * @see https://developers.google.com/protocol-buffers/docs/proto3?hl=en#json + */ +util.toJSONOptions = { + longs: String, + enums: String, + bytes: String, + json: true +}; + +util._configure = function() { + var Buffer = util.Buffer; + /* istanbul ignore if */ + if (!Buffer) { + util._Buffer_from = util._Buffer_allocUnsafe = null; + return; + } + // because node 4.x buffers are incompatible & immutable + // see: https://github.com/dcodeIO/protobuf.js/pull/665 + util._Buffer_from = Buffer.from !== Uint8Array.from && Buffer.from || + /* istanbul ignore next */ + function Buffer_from(value, encoding) { + return new Buffer(value, encoding); + }; + util._Buffer_allocUnsafe = Buffer.allocUnsafe || + /* istanbul ignore next */ + function Buffer_allocUnsafe(size) { + return new Buffer(size); + }; +}; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(38))) + +/***/ }), +/* 41 */ +/***/ (function(module, exports) { + +var core = module.exports = { version: '2.5.1' }; +if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef + + +/***/ }), +/* 42 */ +/***/ (function(module, exports) { + +module.exports = false; + + +/***/ }), +/* 43 */ +/***/ (function(module, exports, __webpack_require__) { + +var redefine = __webpack_require__(29); +module.exports = function (target, src, safe) { + for (var key in src) redefine(target, key, src[key], safe); + return target; +}; + + +/***/ }), +/* 44 */ +/***/ (function(module, exports) { + +module.exports = function (it, Constructor, name, forbiddenField) { + if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) { + throw TypeError(name + ': incorrect invocation!'); + } return it; +}; + + +/***/ }), +/* 45 */ +/***/ (function(module, exports) { + +var toString = {}.toString; + +module.exports = function (it) { + return toString.call(it).slice(8, -1); +}; + + +/***/ }), +/* 46 */ +/***/ (function(module, exports, __webpack_require__) { + +var toInteger = __webpack_require__(36); +var max = Math.max; +var min = Math.min; +module.exports = function (index, length) { + index = toInteger(index); + return index < 0 ? max(index + length, 0) : min(index, length); +}; + + +/***/ }), +/* 47 */ +/***/ (function(module, exports, __webpack_require__) { + +var def = __webpack_require__(10).f; +var has = __webpack_require__(14); +var TAG = __webpack_require__(9)('toStringTag'); + +module.exports = function (it, tag, stat) { + if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag }); +}; + + +/***/ }), +/* 48 */ +/***/ (function(module, exports) { + +module.exports = {}; + + +/***/ }), +/* 49 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) +var has = __webpack_require__(14); +var toObject = __webpack_require__(24); +var IE_PROTO = __webpack_require__(88)('IE_PROTO'); +var ObjectProto = Object.prototype; + +module.exports = Object.getPrototypeOf || function (O) { + O = toObject(O); + if (has(O, IE_PROTO)) return O[IE_PROTO]; + if (typeof O.constructor == 'function' && O instanceof O.constructor) { + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; +}; + + +/***/ }), +/* 50 */ +/***/ (function(module, exports, __webpack_require__) { + +// 22.1.3.31 Array.prototype[@@unscopables] +var UNSCOPABLES = __webpack_require__(9)('unscopables'); +var ArrayProto = Array.prototype; +if (ArrayProto[UNSCOPABLES] == undefined) __webpack_require__(16)(ArrayProto, UNSCOPABLES, {}); +module.exports = function (key) { + ArrayProto[UNSCOPABLES][key] = true; +}; + + +/***/ }), +/* 51 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(5); +module.exports = function (it, TYPE) { + if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!'); + return it; +}; + + +/***/ }), +/* 52 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsNative = __webpack_require__(322), + getValue = __webpack_require__(325); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +module.exports = getNative; + + +/***/ }), +/* 53 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = matrixProduct + +var generatePlan = __webpack_require__(448) + +function shape(arr) { + if(Array.isArray(arr)) { + return [ arr.length, arr[0].length ] + } else { + return arr.shape + } +} + +function checkShapes(out, a, b) { + var os = shape(out) + var as = shape(a) + var bs = shape(b) + if(os[0] !== as[0] || os[1] !== bs[1] || as[1] !== bs[0]) { + throw new Error("Mismatched array shapes for matrix product") + } +} + +function classifyType(m) { + if(Array.isArray(m)) { + if(Array.isArray(m)) { + return [ "r", "native" ] + } + } else if(m.shape && (m.shape.length === 2)) { + if(m.order[0]) { + return [ "r", m.dtype ] + } else { + return [ "c", m.dtype ] + } + } + throw new Error("Unrecognized data type") +} + +var CACHE = {} + +function matrixProduct(out, a, b, alpha, beta) { + if(alpha === undefined) { + alpha = 1.0 + } + if(beta === undefined) { + beta = 0.0 + } + var useAlpha = (alpha !== 1.0) + var useBeta = (beta !== 0.0) + var outType = classifyType(out) + var aType = classifyType(a) + var bType = classifyType(b) + + checkShapes(out, a, b) + + var typeSig = [ outType, aType, bType, useAlpha, useBeta ].join(":") + var proc = CACHE[typeSig] + if(!proc) { + proc = CACHE[typeSig] = generatePlan(outType, aType, bType, useAlpha, useBeta) + } + return proc(out, a, b, alpha, beta) +} + +/***/ }), +/* 54 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = __webpack_require__(5); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function (it, S) { + if (!isObject(it)) return it; + var fn, val; + if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; + if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val; + if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; + throw TypeError("Can't convert object to primitive value"); +}; + + +/***/ }), +/* 55 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O) +var $keys = __webpack_require__(119); +var hiddenKeys = __webpack_require__(90).concat('length', 'prototype'); + +exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return $keys(O, hiddenKeys); +}; + + +/***/ }), +/* 56 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +var anObject = __webpack_require__(7); +var dPs = __webpack_require__(185); +var enumBugKeys = __webpack_require__(90); +var IE_PROTO = __webpack_require__(88)('IE_PROTO'); +var Empty = function () { /* empty */ }; +var PROTOTYPE = 'prototype'; + +// Create object with fake `null` prototype: use iframe Object with cleared prototype +var createDict = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = __webpack_require__(84)('iframe'); + var i = enumBugKeys.length; + var lt = '<'; + var gt = '>'; + var iframeDocument; + iframe.style.display = 'none'; + __webpack_require__(120).appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]]; + return createDict(); +}; + +module.exports = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + Empty[PROTOTYPE] = anObject(O); + result = new Empty(); + Empty[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO] = O; + } else result = createDict(); + return Properties === undefined ? result : dPs(result, Properties); +}; + + +/***/ }), +/* 57 */ +/***/ (function(module, exports, __webpack_require__) { + +// 0 -> Array#forEach +// 1 -> Array#map +// 2 -> Array#filter +// 3 -> Array#some +// 4 -> Array#every +// 5 -> Array#find +// 6 -> Array#findIndex +var ctx = __webpack_require__(23); +var IObject = __webpack_require__(86); +var toObject = __webpack_require__(24); +var toLength = __webpack_require__(12); +var asc = __webpack_require__(186); +module.exports = function (TYPE, $create) { + var IS_MAP = TYPE == 1; + var IS_FILTER = TYPE == 2; + var IS_SOME = TYPE == 3; + var IS_EVERY = TYPE == 4; + var IS_FIND_INDEX = TYPE == 6; + var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; + var create = $create || asc; + return function ($this, callbackfn, that) { + var O = toObject($this); + var self = IObject(O); + var f = ctx(callbackfn, that, 3); + var length = toLength(self.length); + var index = 0; + var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined; + var val, res; + for (;length > index; index++) if (NO_HOLES || index in self) { + val = self[index]; + res = f(val, index, O); + if (TYPE) { + if (IS_MAP) result[index] = res; // map + else if (res) switch (TYPE) { + case 3: return true; // some + case 5: return val; // find + case 6: return index; // findIndex + case 2: result.push(val); // filter + } else if (IS_EVERY) return false; // every + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result; + }; +}; + + +/***/ }), +/* 58 */ +/***/ (function(module, exports) { + +exports.f = {}.propertyIsEnumerable; + + +/***/ }), +/* 59 */ +/***/ (function(module, exports, __webpack_require__) { + +var arrayLikeKeys = __webpack_require__(298), + baseKeys = __webpack_require__(307), + isArrayLike = __webpack_require__(63); + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); +} + +module.exports = keys; + + +/***/ }), +/* 60 */ +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(61), + getRawTag = __webpack_require__(301), + objectToString = __webpack_require__(302); + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +module.exports = baseGetTag; + + +/***/ }), +/* 61 */ +/***/ (function(module, exports, __webpack_require__) { + +var root = __webpack_require__(22); + +/** Built-in value references. */ +var Symbol = root.Symbol; + +module.exports = Symbol; + + +/***/ }), +/* 62 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +module.exports = isObjectLike; + + +/***/ }), +/* 63 */ +/***/ (function(module, exports, __webpack_require__) { + +var isFunction = __webpack_require__(144), + isLength = __webpack_require__(107); + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +module.exports = isArrayLike; + + +/***/ }), +/* 64 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +module.exports = isObject; + + +/***/ }), +/* 65 */ +/***/ (function(module, exports) { + +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + + +/***/ }), +/* 66 */ +/***/ (function(module, exports, __webpack_require__) { + +var iota = __webpack_require__(413) +var isBuffer = __webpack_require__(160) + +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; iMath.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=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=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 index; index++) { + result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if (result === BREAK || result === RETURN) return result; + } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) { + result = call(iterator, f, step.value, entries); + if (result === BREAK || result === RETURN) return result; + } +}; +exports.BREAK = BREAK; +exports.RETURN = RETURN; + + +/***/ }), +/* 71 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var global = __webpack_require__(6); +var $export = __webpack_require__(0); +var redefine = __webpack_require__(29); +var redefineAll = __webpack_require__(43); +var meta = __webpack_require__(31); +var forOf = __webpack_require__(70); +var anInstance = __webpack_require__(44); +var isObject = __webpack_require__(5); +var fails = __webpack_require__(8); +var $iterDetect = __webpack_require__(69); +var setToStringTag = __webpack_require__(47); +var inheritIfRequired = __webpack_require__(198); + +module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) { + var Base = global[NAME]; + var C = Base; + var ADDER = IS_MAP ? 'set' : 'add'; + var proto = C && C.prototype; + var O = {}; + var fixMethod = function (KEY) { + var fn = proto[KEY]; + redefine(proto, KEY, + KEY == 'delete' ? function (a) { + return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'has' ? function has(a) { + return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'get' ? function get(a) { + return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a); + } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; } + : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; } + ); + }; + if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () { + new C().entries().next(); + }))) { + // create collection constructor + C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); + redefineAll(C.prototype, methods); + meta.NEED = true; + } else { + var instance = new C(); + // early implementations not supports chaining + var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance; + // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false + var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); }); + // most early implementations doesn't supports iterables, most modern - not close it correctly + var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new + // for early implementations -0 and +0 not the same + var BUGGY_ZERO = !IS_WEAK && fails(function () { + // V8 ~ Chromium 42- fails only with 5+ elements + var $instance = new C(); + var index = 5; + while (index--) $instance[ADDER](index, index); + return !$instance.has(-0); + }); + if (!ACCEPT_ITERABLES) { + C = wrapper(function (target, iterable) { + anInstance(target, C, NAME); + var that = inheritIfRequired(new Base(), target, C); + if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that); + return that; + }); + C.prototype = proto; + proto.constructor = C; + } + if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) { + fixMethod('delete'); + fixMethod('has'); + IS_MAP && fixMethod('get'); + } + if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER); + // weak collections should not contains .clear method + if (IS_WEAK && proto.clear) delete proto.clear; + } + + setToStringTag(C, NAME); + + O[NAME] = C; + $export($export.G + $export.W + $export.F * (C != Base), O); + + if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP); + + return C; +}; + + +/***/ }), +/* 72 */ +/***/ (function(module, exports) { + +exports.f = Object.getOwnPropertySymbols; + + +/***/ }), +/* 73 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var hide = __webpack_require__(16); +var redefine = __webpack_require__(29); +var fails = __webpack_require__(8); +var defined = __webpack_require__(30); +var wks = __webpack_require__(9); + +module.exports = function (KEY, length, exec) { + var SYMBOL = wks(KEY); + var fns = exec(defined, SYMBOL, ''[KEY]); + var strfn = fns[0]; + var rxfn = fns[1]; + if (fails(function () { + var O = {}; + O[SYMBOL] = function () { return 7; }; + return ''[KEY](O) != 7; + })) { + redefine(String.prototype, KEY, strfn); + hide(RegExp.prototype, SYMBOL, length == 2 + // 21.2.5.8 RegExp.prototype[@@replace](string, replaceValue) + // 21.2.5.11 RegExp.prototype[@@split](string, limit) + ? function (string, arg) { return rxfn.call(string, this, arg); } + // 21.2.5.6 RegExp.prototype[@@match](string) + // 21.2.5.9 RegExp.prototype[@@search](string) + : function (string) { return rxfn.call(string, this); } + ); + } +}; + + +/***/ }), +/* 74 */ +/***/ (function(module, exports) { + +module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + if(!module.children) module.children = []; + Object.defineProperty(module, "loaded", { + enumerable: true, + get: function() { + return module.l; + } + }); + Object.defineProperty(module, "id", { + enumerable: true, + get: function() { + return module.i; + } + }); + module.webpackPolyfill = 1; + } + return module; +}; + + +/***/ }), +/* 75 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsEqual = __webpack_require__(108); + +/** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ +function isEqual(value, other) { + return baseIsEqual(value, other); +} + +module.exports = isEqual; + + +/***/ }), +/* 76 */ +/***/ (function(module, exports, __webpack_require__) { + +var listCacheClear = __webpack_require__(312), + listCacheDelete = __webpack_require__(313), + listCacheGet = __webpack_require__(314), + listCacheHas = __webpack_require__(315), + listCacheSet = __webpack_require__(316); + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; + +module.exports = ListCache; + + +/***/ }), +/* 77 */ +/***/ (function(module, exports, __webpack_require__) { + +var eq = __webpack_require__(109); + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +module.exports = assocIndexOf; + + +/***/ }), +/* 78 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(52); + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +module.exports = nativeCreate; + + +/***/ }), +/* 79 */ +/***/ (function(module, exports, __webpack_require__) { + +var isKeyable = __webpack_require__(334); + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +module.exports = getMapData; + + +/***/ }), +/* 80 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseMatches = __webpack_require__(359), + baseMatchesProperty = __webpack_require__(362), + identity = __webpack_require__(154), + isArray = __webpack_require__(17), + property = __webpack_require__(372); + +/** + * The base implementation of `_.iteratee`. + * + * @private + * @param {*} [value=_.identity] The value to convert to an iteratee. + * @returns {Function} Returns the iteratee. + */ +function baseIteratee(value) { + // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. + // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. + if (typeof value == 'function') { + return value; + } + if (value == null) { + return identity; + } + if (typeof value == 'object') { + return isArray(value) + ? baseMatchesProperty(value[0], value[1]) + : baseMatches(value); + } + return property(value); +} + +module.exports = baseIteratee; + + +/***/ }), +/* 81 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseGetTag = __webpack_require__(60), + isObjectLike = __webpack_require__(62); + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); +} + +module.exports = isSymbol; + + +/***/ }), +/* 82 */ +/***/ (function(module, exports, __webpack_require__) { + +var isSymbol = __webpack_require__(81); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** + * Converts `value` to a string key if it's not a string or symbol. + * + * @private + * @param {*} value The value to inspect. + * @returns {string|symbol} Returns the key. + */ +function toKey(value) { + if (typeof value == 'string' || isSymbol(value)) { + return value; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +module.exports = toKey; + + +/***/ }), +/* 83 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports.swap = __webpack_require__(464); +module.exports.scal = __webpack_require__(465); +module.exports.copy = __webpack_require__(466); +module.exports.axpy = __webpack_require__(467); +module.exports.dot = __webpack_require__(468); +module.exports.cpsc = __webpack_require__(469); +module.exports.nrm2 = __webpack_require__(470); +module.exports.asum = __webpack_require__(471); +module.exports.iamax = __webpack_require__(472); +module.exports.rotg = __webpack_require__(473); + + +/***/ }), +/* 84 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(5); +var document = __webpack_require__(6).document; +// typeof document.createElement is 'object' in old IE +var is = isObject(document) && isObject(document.createElement); +module.exports = function (it) { + return is ? document.createElement(it) : {}; +}; + + +/***/ }), +/* 85 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(6); +var hide = __webpack_require__(16); +var uid = __webpack_require__(34); +var TYPED = uid('typed_array'); +var VIEW = uid('view'); +var ABV = !!(global.ArrayBuffer && global.DataView); +var CONSTR = ABV; +var i = 0; +var l = 9; +var Typed; + +var TypedArrayConstructors = ( + 'Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array' +).split(','); + +while (i < l) { + if (Typed = global[TypedArrayConstructors[i++]]) { + hide(Typed.prototype, TYPED, true); + hide(Typed.prototype, VIEW, true); + } else CONSTR = false; +} + +module.exports = { + ABV: ABV, + CONSTR: CONSTR, + TYPED: TYPED, + VIEW: VIEW +}; + + +/***/ }), +/* 86 */ +/***/ (function(module, exports, __webpack_require__) { + +// fallback for non-array-like ES3 and non-enumerable old V8 strings +var cof = __webpack_require__(45); +// eslint-disable-next-line no-prototype-builtins +module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) { + return cof(it) == 'String' ? it.split('') : Object(it); +}; + + +/***/ }), +/* 87 */ +/***/ (function(module, exports, __webpack_require__) { + +// false -> Array#indexOf +// true -> Array#includes +var toIObject = __webpack_require__(20); +var toLength = __webpack_require__(12); +var toAbsoluteIndex = __webpack_require__(46); +module.exports = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIObject($this); + var length = toLength(O.length); + var index = toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) if (IS_INCLUDES || index in O) { + if (O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; +}; + + +/***/ }), +/* 88 */ +/***/ (function(module, exports, __webpack_require__) { + +var shared = __webpack_require__(89)('keys'); +var uid = __webpack_require__(34); +module.exports = function (key) { + return shared[key] || (shared[key] = uid(key)); +}; + + +/***/ }), +/* 89 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(6); +var SHARED = '__core-js_shared__'; +var store = global[SHARED] || (global[SHARED] = {}); +module.exports = function (key) { + return store[key] || (store[key] = {}); +}; + + +/***/ }), +/* 90 */ +/***/ (function(module, exports) { + +// IE 8- don't enum bug keys +module.exports = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' +).split(','); + + +/***/ }), +/* 91 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length) + +var toObject = __webpack_require__(24); +var toAbsoluteIndex = __webpack_require__(46); +var toLength = __webpack_require__(12); +module.exports = function fill(value /* , start = 0, end = @length */) { + var O = toObject(this); + var length = toLength(O.length); + var aLen = arguments.length; + var index = toAbsoluteIndex(aLen > 1 ? arguments[1] : undefined, length); + var end = aLen > 2 ? arguments[2] : undefined; + var endPos = end === undefined ? length : toAbsoluteIndex(end, length); + while (endPos > index) O[index++] = value; + return O; +}; + + +/***/ }), +/* 92 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.3.20 SpeciesConstructor(O, defaultConstructor) +var anObject = __webpack_require__(7); +var aFunction = __webpack_require__(35); +var SPECIES = __webpack_require__(9)('species'); +module.exports = function (O, D) { + var C = anObject(O).constructor; + var S; + return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); +}; + + +/***/ }), +/* 93 */ +/***/ (function(module, exports, __webpack_require__) { + +// getting tag from 19.1.3.6 Object.prototype.toString() +var cof = __webpack_require__(45); +var TAG = __webpack_require__(9)('toStringTag'); +// ES3 wrong here +var ARG = cof(function () { return arguments; }()) == 'Arguments'; + +// fallback for IE11 Script Access Denied error +var tryGet = function (it, key) { + try { + return it[key]; + } catch (e) { /* empty */ } +}; + +module.exports = function (it) { + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? cof(O) + // ES3 arguments fallback + : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; +}; + + +/***/ }), +/* 94 */ +/***/ (function(module, exports, __webpack_require__) { + +// check on default Array iterator +var Iterators = __webpack_require__(48); +var ITERATOR = __webpack_require__(9)('iterator'); +var ArrayProto = Array.prototype; + +module.exports = function (it) { + return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); +}; + + +/***/ }), +/* 95 */ +/***/ (function(module, exports, __webpack_require__) { + +var classof = __webpack_require__(93); +var ITERATOR = __webpack_require__(9)('iterator'); +var Iterators = __webpack_require__(48); +module.exports = __webpack_require__(41).getIteratorMethod = function (it) { + if (it != undefined) return it[ITERATOR] + || it['@@iterator'] + || Iterators[classof(it)]; +}; + + +/***/ }), +/* 96 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var addToUnscopables = __webpack_require__(50); +var step = __webpack_require__(122); +var Iterators = __webpack_require__(48); +var toIObject = __webpack_require__(20); + +// 22.1.3.4 Array.prototype.entries() +// 22.1.3.13 Array.prototype.keys() +// 22.1.3.29 Array.prototype.values() +// 22.1.3.30 Array.prototype[@@iterator]() +module.exports = __webpack_require__(123)(Array, 'Array', function (iterated, kind) { + this._t = toIObject(iterated); // target + this._i = 0; // next index + this._k = kind; // kind +// 22.1.5.2.1 %ArrayIteratorPrototype%.next() +}, function () { + var O = this._t; + var kind = this._k; + var index = this._i++; + if (!O || index >= O.length) { + this._t = undefined; + return step(1); + } + if (kind == 'keys') return step(0, index); + if (kind == 'values') return step(0, O[index]); + return step(0, [index, O[index]]); +}, 'values'); + +// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) +Iterators.Arguments = Iterators.Array; + +addToUnscopables('keys'); +addToUnscopables('values'); +addToUnscopables('entries'); + + +/***/ }), +/* 97 */ +/***/ (function(module, exports, __webpack_require__) { + +// Works with __proto__ only. Old v8 can't work with null proto objects. +/* eslint-disable no-proto */ +var isObject = __webpack_require__(5); +var anObject = __webpack_require__(7); +var check = function (O, proto) { + anObject(O); + if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!"); +}; +module.exports = { + set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line + function (test, buggy, set) { + try { + set = __webpack_require__(23)(Function.call, __webpack_require__(26).f(Object.prototype, '__proto__').set, 2); + set(test, []); + buggy = !(test instanceof Array); + } catch (e) { buggy = true; } + return function setPrototypeOf(O, proto) { + check(O, proto); + if (buggy) O.__proto__ = proto; + else set(O, proto); + return O; + }; + }({}, false) : undefined), + check: check +}; + + +/***/ }), +/* 98 */ +/***/ (function(module, exports, __webpack_require__) { + +var ctx = __webpack_require__(23); +var invoke = __webpack_require__(129); +var html = __webpack_require__(120); +var cel = __webpack_require__(84); +var global = __webpack_require__(6); +var process = global.process; +var setTask = global.setImmediate; +var clearTask = global.clearImmediate; +var MessageChannel = global.MessageChannel; +var Dispatch = global.Dispatch; +var counter = 0; +var queue = {}; +var ONREADYSTATECHANGE = 'onreadystatechange'; +var defer, channel, port; +var run = function () { + var id = +this; + // eslint-disable-next-line no-prototype-builtins + if (queue.hasOwnProperty(id)) { + var fn = queue[id]; + delete queue[id]; + fn(); + } +}; +var listener = function (event) { + run.call(event.data); +}; +// Node.js 0.9+ & IE10+ has setImmediate, otherwise: +if (!setTask || !clearTask) { + setTask = function setImmediate(fn) { + var args = []; + var i = 1; + while (arguments.length > i) args.push(arguments[i++]); + queue[++counter] = function () { + // eslint-disable-next-line no-new-func + invoke(typeof fn == 'function' ? fn : Function(fn), args); + }; + defer(counter); + return counter; + }; + clearTask = function clearImmediate(id) { + delete queue[id]; + }; + // Node.js 0.8- + if (__webpack_require__(45)(process) == 'process') { + defer = function (id) { + process.nextTick(ctx(run, id, 1)); + }; + // Sphere (JS game engine) Dispatch API + } else if (Dispatch && Dispatch.now) { + defer = function (id) { + Dispatch.now(ctx(run, id, 1)); + }; + // Browsers with MessageChannel, includes WebWorkers + } else if (MessageChannel) { + channel = new MessageChannel(); + port = channel.port2; + channel.port1.onmessage = listener; + defer = ctx(port.postMessage, port, 1); + // Browsers with postMessage, skip WebWorkers + // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' + } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) { + defer = function (id) { + global.postMessage(id + '', '*'); + }; + global.addEventListener('message', listener, false); + // IE8- + } else if (ONREADYSTATECHANGE in cel('script')) { + defer = function (id) { + html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () { + html.removeChild(this); + run.call(id); + }; + }; + // Rest old browsers + } else { + defer = function (id) { + setTimeout(ctx(run, id, 1), 0); + }; + } +} +module.exports = { + set: setTask, + clear: clearTask +}; + + +/***/ }), +/* 99 */ +/***/ (function(module, exports, __webpack_require__) { + +// helper for String#{startsWith, endsWith, includes} +var isRegExp = __webpack_require__(135); +var defined = __webpack_require__(30); + +module.exports = function (that, searchString, NAME) { + if (isRegExp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!"); + return String(defined(that)); +}; + + +/***/ }), +/* 100 */ +/***/ (function(module, exports, __webpack_require__) { + +var MATCH = __webpack_require__(9)('match'); +module.exports = function (KEY) { + var re = /./; + try { + '/./'[KEY](re); + } catch (e) { + try { + re[MATCH] = false; + return !'/./'[KEY](re); + } catch (f) { /* empty */ } + } return true; +}; + + +/***/ }), +/* 101 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var $defineProperty = __webpack_require__(10); +var createDesc = __webpack_require__(33); + +module.exports = function (object, index, value) { + if (index in object) $defineProperty.f(object, index, createDesc(0, value)); + else object[index] = value; +}; + + +/***/ }), +/* 102 */ +/***/ (function(module, exports) { + +module.exports = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' + + '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF'; + + +/***/ }), +/* 103 */ +/***/ (function(module, exports) { + +// 20.2.2.28 Math.sign(x) +module.exports = Math.sign || function sign(x) { + // eslint-disable-next-line no-self-compare + return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1; +}; + + +/***/ }), +/* 104 */ +/***/ (function(module, exports) { + +// 20.2.2.14 Math.expm1(x) +var $expm1 = Math.expm1; +module.exports = (!$expm1 + // Old FF bug + || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168 + // Tor Browser bug + || $expm1(-2e-17) != -2e-17 +) ? function expm1(x) { + return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : Math.exp(x) - 1; +} : $expm1; + + +/***/ }), +/* 105 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsArguments = __webpack_require__(300), + isObjectLike = __webpack_require__(62); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; + +module.exports = isArguments; + + +/***/ }), +/* 106 */ +/***/ (function(module, exports) { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + length = length == null ? MAX_SAFE_INTEGER : length; + return !!length && + (typeof value == 'number' || reIsUint.test(value)) && + (value > -1 && value % 1 == 0 && value < length); +} + +module.exports = isIndex; + + +/***/ }), +/* 107 */ +/***/ (function(module, exports) { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +module.exports = isLength; + + +/***/ }), +/* 108 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsEqualDeep = __webpack_require__(311), + isObjectLike = __webpack_require__(62); + +/** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ +function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); +} + +module.exports = baseIsEqual; + + +/***/ }), +/* 109 */ +/***/ (function(module, exports) { + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +module.exports = eq; + + +/***/ }), +/* 110 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(52), + root = __webpack_require__(22); + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'); + +module.exports = Map; + + +/***/ }), +/* 111 */ +/***/ (function(module, exports, __webpack_require__) { + +var mapCacheClear = __webpack_require__(326), + mapCacheDelete = __webpack_require__(333), + mapCacheGet = __webpack_require__(335), + mapCacheHas = __webpack_require__(336), + mapCacheSet = __webpack_require__(337); + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +module.exports = MapCache; + + +/***/ }), +/* 112 */ +/***/ (function(module, exports, __webpack_require__) { + +var isArray = __webpack_require__(17), + isSymbol = __webpack_require__(81); + +/** Used to match property names within property paths. */ +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/; + +/** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ +function isKey(value, object) { + if (isArray(value)) { + return false; + } + var type = typeof value; + if (type == 'number' || type == 'symbol' || type == 'boolean' || + value == null || isSymbol(value)) { + return true; + } + return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || + (object != null && value in Object(object)); +} + +module.exports = isKey; + + +/***/ }), +/* 113 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(process) { + +var utils = __webpack_require__(15); +var normalizeHeaderName = __webpack_require__(394); + +var DEFAULT_CONTENT_TYPE = { + 'Content-Type': 'application/x-www-form-urlencoded' +}; + +function setContentTypeIfUnset(headers, value) { + if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) { + headers['Content-Type'] = value; + } +} + +function getDefaultAdapter() { + var adapter; + if (typeof XMLHttpRequest !== 'undefined') { + // For browsers use XHR adapter + adapter = __webpack_require__(161); + } else if (typeof process !== 'undefined') { + // For node use HTTP adapter + adapter = __webpack_require__(161); + } + return adapter; +} + +var defaults = { + adapter: getDefaultAdapter(), + + transformRequest: [function transformRequest(data, headers) { + normalizeHeaderName(headers, 'Content-Type'); + if (utils.isFormData(data) || + utils.isArrayBuffer(data) || + utils.isBuffer(data) || + utils.isStream(data) || + utils.isFile(data) || + utils.isBlob(data) + ) { + return data; + } + if (utils.isArrayBufferView(data)) { + return data.buffer; + } + if (utils.isURLSearchParams(data)) { + setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); + return data.toString(); + } + if (utils.isObject(data)) { + setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); + return JSON.stringify(data); + } + return data; + }], + + transformResponse: [function transformResponse(data) { + /*eslint no-param-reassign:0*/ + if (typeof data === 'string') { + try { + data = JSON.parse(data); + } catch (e) { /* Ignore */ } + } + return data; + }], + + timeout: 0, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + + maxContentLength: -1, + + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300; + } +}; + +defaults.headers = { + common: { + 'Accept': 'application/json, text/plain, */*' + } +}; + +utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { + defaults.headers[method] = {}; +}); + +utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); +}); + +module.exports = defaults; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(65))) + +/***/ }), +/* 114 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__InputLayer__ = __webpack_require__(410); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "InputLayer", function() { return __WEBPACK_IMPORTED_MODULE_0__InputLayer__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__advanced_activations__ = __webpack_require__(416); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "LeakyReLU", function() { return __WEBPACK_IMPORTED_MODULE_1__advanced_activations__["b"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "PReLU", function() { return __WEBPACK_IMPORTED_MODULE_1__advanced_activations__["c"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "ELU", function() { return __WEBPACK_IMPORTED_MODULE_1__advanced_activations__["a"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "ThresholdedReLU", function() { return __WEBPACK_IMPORTED_MODULE_1__advanced_activations__["d"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__convolutional__ = __webpack_require__(433); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Conv1D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["a"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Conv2D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["b"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SeparableConv2D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["h"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Conv2DTranspose", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["c"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Conv3D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["d"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Cropping1D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["e"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Cropping2D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["f"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Cropping3D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["g"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "UpSampling1D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["i"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "UpSampling2D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["j"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "UpSampling3D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["k"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "ZeroPadding1D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["l"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "ZeroPadding2D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["m"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "ZeroPadding3D", function() { return __WEBPACK_IMPORTED_MODULE_2__convolutional__["n"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__core__ = __webpack_require__(461); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Dense", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["b"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Activation", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["a"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Dropout", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["c"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SpatialDropout1D", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["h"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SpatialDropout2D", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["i"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SpatialDropout3D", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["j"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Flatten", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["d"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Reshape", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["g"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Permute", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["e"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "RepeatVector", function() { return __WEBPACK_IMPORTED_MODULE_3__core__["f"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__embeddings__ = __webpack_require__(504); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Embedding", function() { return __WEBPACK_IMPORTED_MODULE_4__embeddings__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__merge__ = __webpack_require__(506); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Add", function() { return __WEBPACK_IMPORTED_MODULE_5__merge__["a"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Subtract", function() { return __WEBPACK_IMPORTED_MODULE_5__merge__["h"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Multiply", function() { return __WEBPACK_IMPORTED_MODULE_5__merge__["g"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Average", function() { return __WEBPACK_IMPORTED_MODULE_5__merge__["b"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Maximum", function() { return __WEBPACK_IMPORTED_MODULE_5__merge__["e"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Minimum", function() { return __WEBPACK_IMPORTED_MODULE_5__merge__["f"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Concatenate", function() { return __WEBPACK_IMPORTED_MODULE_5__merge__["c"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Dot", function() { return __WEBPACK_IMPORTED_MODULE_5__merge__["d"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__noise__ = __webpack_require__(517); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GaussianDropout", function() { return __WEBPACK_IMPORTED_MODULE_6__noise__["a"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GaussianNoise", function() { return __WEBPACK_IMPORTED_MODULE_6__noise__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__normalization__ = __webpack_require__(520); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "BatchNormalization", function() { return __WEBPACK_IMPORTED_MODULE_7__normalization__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__pooling__ = __webpack_require__(522); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MaxPooling1D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["j"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MaxPooling2D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["k"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "MaxPooling3D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["l"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "AveragePooling1D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["a"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "AveragePooling2D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["b"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "AveragePooling3D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["c"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GlobalMaxPooling1D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["g"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GlobalMaxPooling2D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["h"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GlobalMaxPooling3D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["i"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GlobalAveragePooling1D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["d"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GlobalAveragePooling2D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["e"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GlobalAveragePooling3D", function() { return __WEBPACK_IMPORTED_MODULE_8__pooling__["f"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__recurrent__ = __webpack_require__(179); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "SimpleRNN", function() { return __WEBPACK_IMPORTED_MODULE_9__recurrent__["SimpleRNN"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "LSTM", function() { return __WEBPACK_IMPORTED_MODULE_9__recurrent__["LSTM"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "GRU", function() { return __WEBPACK_IMPORTED_MODULE_9__recurrent__["GRU"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__wrappers__ = __webpack_require__(538); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "TimeDistributed", function() { return __WEBPACK_IMPORTED_MODULE_10__wrappers__["b"]; }); +/* harmony namespace reexport (by provided) */ __webpack_require__.d(__webpack_exports__, "Bidirectional", function() { return __WEBPACK_IMPORTED_MODULE_10__wrappers__["a"]; }); + + + + + + + + + + + + + +/***/ }), +/* 115 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Conv2D; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Layer__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__activations__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__webgl_dynamic_createGLSLProgram__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__utils_tensorUtils__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_ndarray_ops__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_ndarray_gemm__ = __webpack_require__(53); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_ndarray_gemm___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_ndarray_gemm__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__activations_programSources__ = __webpack_require__(28); +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +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"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _slicedToArray(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"); } } + +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +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); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } 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 mapInputProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(indexMap, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +var mapInputFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D indexMap;\r\nuniform int inputCols;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(indexMap, 0);\r\n int out_x = int(float(outputSize[0]) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n int index = texelFetch(indexMap, ivec2(out_x, out_y), 0).r;\r\n\r\n if (index != -1) {\r\n int rowIndex = int(floor(float(index) / float(inputCols)));\r\n int colIndex = int(mod(float(index), float(inputCols)));\r\n int fragmentIndex = int(floor(float(rowIndex) / float(inputSize[1])));\r\n rowIndex = int(mod(float(rowIndex), float(inputSize[1])));\r\n colIndex = fragmentIndex * inputCols + colIndex;\r\n float val = texelFetch(x, ivec2(colIndex, rowIndex), 0).r;\r\n outColor = vec4(val);\r\n } else {\r\n outColor = vec4(0.0);\r\n }\r\n}\r\n"; +var matMulProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D A;\r\nuniform sampler2D B;\r\nuniform sampler2D C;\r\nuniform bool addC;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 A_size = textureSize(A, 0);\r\n ivec2 B_size = textureSize(B, 0);\r\n int out_x = int(float(B_size[0]) * outTex.x);\r\n int out_y = int(float(A_size[1]) * outTex.y);\r\n int commonDim = A_size[0];\r\n\r\n float sum = 0.;\r\n for (int i = 0; i < commonDim; ++i) {\r\n float a = texelFetch(A, ivec2(i, out_y), 0).r;\r\n float b = texelFetch(B, ivec2(out_x, i), 0).r;\r\n sum += a * b;\r\n }\r\n\r\n if (addC) {\r\n sum += texelFetch(C, ivec2(out_x, 0), 0).r;\r\n }\r\n\r\n outColor = vec4(sum);\r\n}\r\n"; + + +var Conv2D = function (_Layer) { + _inherits(Conv2D, _Layer); + + function Conv2D() { + var _this; + + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, Conv2D); + + _this = _possibleConstructorReturn(this, (Conv2D.__proto__ || Object.getPrototypeOf(Conv2D)).call(this, attrs)); + _this.layerClass = 'Conv2D'; + var _attrs$filters = attrs.filters, + filters = _attrs$filters === void 0 ? 1 : _attrs$filters, + _attrs$kernel_size = attrs.kernel_size, + kernel_size = _attrs$kernel_size === void 0 ? [3, 3] : _attrs$kernel_size, + _attrs$strides = attrs.strides, + strides = _attrs$strides === void 0 ? [1, 1] : _attrs$strides, + _attrs$padding = attrs.padding, + padding = _attrs$padding === void 0 ? 'valid' : _attrs$padding, + _attrs$data_format = attrs.data_format, + data_format = _attrs$data_format === void 0 ? 'channels_last' : _attrs$data_format, + _attrs$dilation_rate = attrs.dilation_rate, + dilation_rate = _attrs$dilation_rate === void 0 ? [1, 1] : _attrs$dilation_rate, + _attrs$activation = attrs.activation, + activation = _attrs$activation === void 0 ? 'linear' : _attrs$activation, + _attrs$use_bias = attrs.use_bias, + use_bias = _attrs$use_bias === void 0 ? true : _attrs$use_bias; + + if (Array.isArray(kernel_size)) { + _this.kernelShape = [filters].concat(_toConsumableArray(kernel_size)); + } else { + _this.kernelShape = [filters, kernel_size, kernel_size]; + } + + if (Array.isArray(strides)) { + _this.strides = strides; + } else { + _this.strides = [strides, strides]; + } + + if (padding === 'valid' || padding === 'same') { + _this.padding = padding; + } else { + _this.throwError('Invalid padding.'); + } + + if (data_format === 'channels_last' || data_format === 'channels_first') { + _this.dataFormat = data_format; + } else { + _this.throwError('Only channels_last and channels_first data formats are allowed.'); + } + + if (Array.isArray(dilation_rate)) { + _this.dilationRate = dilation_rate; + } else { + _this.dilationRate = [dilation_rate, dilation_rate]; + } + + if ((_this.dilationRate[0] !== 1 || _this.dilationRate[1] !== 1) && (_this.strides[0] !== 1 || _this.strides[1] !== 1)) { + _this.throwError("Incompatible combination of dilation_rate with strides."); + } + + _this.activation = activation; + _this.activationFunc = __WEBPACK_IMPORTED_MODULE_2__activations__[activation]; + _this.useBias = use_bias; + _this.params = _this.useBias ? ['kernel', 'bias'] : ['kernel']; + + if (_this.gpu) { + _this.mapInputProgram = __WEBPACK_IMPORTED_MODULE_3__WebGL2__["b" /* webgl2 */].compileProgram(mapInputProgramSource); + _this.mapInputFragmentsProgram = __WEBPACK_IMPORTED_MODULE_3__WebGL2__["b" /* webgl2 */].compileProgram(mapInputFragmentsProgramSource); + _this.matMulProgram = __WEBPACK_IMPORTED_MODULE_3__WebGL2__["b" /* webgl2 */].compileProgram(matMulProgramSource); + _this.activationProgram = __WEBPACK_IMPORTED_MODULE_3__WebGL2__["b" /* webgl2 */].compileProgram(__WEBPACK_IMPORTED_MODULE_8__activations_programSources__[_this.activation]); + } + + return _this; + } + + _createClass(Conv2D, [{ + key: "setWeights", + value: function setWeights(weightsArr) { + if (this.dataFormat === 'channels_first') { + weightsArr[0].tensor = weightsArr[0].tensor.transpose(2, 3, 1, 0); + } + + _get(Conv2D.prototype.__proto__ || Object.getPrototypeOf(Conv2D.prototype), "setWeights", this).call(this, weightsArr, false); + + this._w2row(); + + if (this.gpu) { + this.weights['kernel'] = this.wRowsMat; + this.weights['kernel'].createGLTexture({ + type: '2d', + format: 'float' + }); + + if (this.useBias) { + this.weights['bias'].createGLTexture({ + type: '2d', + format: 'float' + }); + } + } + } + }, { + key: "call", + value: function call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + }, { + key: "_calcOutputShape", + value: function _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + var inputRows = inputShape[0]; + var inputCols = inputShape[1]; + + var _kernelShape = _slicedToArray(this.kernelShape, 3), + nbFilter = _kernelShape[0], + nbRow = _kernelShape[1], + nbCol = _kernelShape[2]; + + var nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + var nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + var outputRows = this.padding === 'same' ? Math.floor((inputRows + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputRows - nbRowDilated + this.strides[0]) / this.strides[0]); + var outputCols = this.padding === 'same' ? Math.floor((inputCols + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputCols - nbColDilated + this.strides[1]) / this.strides[1]); + var outputChannels = nbFilter; + var paddingRow = this.padding === 'same' ? Math.max(0, Math.floor((outputRows - 1) * this.strides[0] + nbRowDilated - inputRows)) : 0; + var paddingCol = this.padding === 'same' ? Math.max(0, Math.floor((outputCols - 1) * this.strides[1] + nbColDilated - inputCols)) : 0; + var paddingRowBefore = Math.floor(paddingRow / 2); + var paddingRowAfter = paddingRow - paddingRowBefore; + var paddingColBefore = Math.floor(paddingCol / 2); + var paddingColAfter = paddingCol - paddingColBefore; + this.outputShape = [outputRows, outputCols, outputChannels]; + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]; + } + }, { + key: "_padInput", + value: function _padInput(x) { + var padValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + + if (this.padding === 'same') { + var _x$tensor$shape = _slicedToArray(x.tensor.shape, 3), + inputRows = _x$tensor$shape[0], + inputCols = _x$tensor$shape[1], + inputChannels = _x$tensor$shape[2]; + + var _inputPadding = _slicedToArray(this.inputPadding, 4), + paddingRowBefore = _inputPadding[0], + paddingRowAfter = _inputPadding[1], + paddingColBefore = _inputPadding[2], + paddingColAfter = _inputPadding[3]; + + var newRows = inputRows + paddingRowBefore + paddingRowAfter; + var newCols = inputCols + paddingColBefore + paddingColAfter; + + var _x = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [newRows, newCols, inputChannels]); + + if (padValue !== 0) { + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assigns(_x.tensor, padValue); + } + + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assign(_x.tensor.hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels).lo(paddingRowBefore, paddingColBefore, 0), x.tensor); + return _x; + } + + return x; + } + }, { + key: "_im2col", + value: function _im2col(x) { + var _x$tensor$shape2 = _slicedToArray(x.tensor.shape, 3), + inputRows = _x$tensor$shape2[0], + inputCols = _x$tensor$shape2[1], + inputChannels = _x$tensor$shape2[2]; + + var nbRow = this.kernelShape[1]; + var nbCol = this.kernelShape[2]; + var outputRows = this.outputShape[0]; + var outputCols = this.outputShape[1]; + var nbPatches = outputRows * outputCols; + var patchLen = nbRow * nbCol * inputChannels; + var nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + var nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + + if (!this.imColsMat) { + this.imColsMat = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [nbPatches, patchLen]); + } + + if (nbRowDilated === 1 && nbColDilated === 1 && this.strides[0] === 1 && this.strides[1] === 1) { + this.imColsMat.replaceTensorData(x.tensor.data); + return this.imColsMat; + } + + var patch = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [nbRow, nbCol, inputChannels]); + var offset = 0; + + for (var i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.strides[0]) { + for (var j = 0, _limit = inputCols - nbColDilated; j <= _limit; j += this.strides[1]) { + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assign(patch.tensor, x.tensor.hi(i + nbRowDilated, j + nbColDilated, inputChannels).lo(i, j, 0).step(this.dilationRate[0], this.dilationRate[1], 1)); + this.imColsMat.tensor.data.set(patch.tensor.data, offset); + offset += patchLen; + } + } + + return this.imColsMat; + } + }, { + key: "_w2row", + value: function _w2row() { + var inputChannels = this.weights['kernel'].tensor.shape[2]; + + var _kernelShape2 = _slicedToArray(this.kernelShape, 3), + nbFilter = _kernelShape2[0], + nbRow = _kernelShape2[1], + nbCol = _kernelShape2[2]; + + var patchLen = nbRow * nbCol * inputChannels; + this.wRowsMat = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [patchLen, nbFilter]); + var patch = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [nbRow, nbCol, inputChannels]); + var patchRaveled = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [patchLen]); + + for (var n = 0; n < nbFilter; n++) { + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assign(patch.tensor, this.weights['kernel'].tensor.pick(null, null, null, n)); + patchRaveled.replaceTensorData(patch.tensor.data); + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assign(this.wRowsMat.tensor.pick(null, n), patchRaveled.tensor); + } + + return this.wRowsMat; + } + }, { + key: "_callCPU", + value: function _callCPU(x) { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._im2col(x); + + var nbFilter = this.kernelShape[0]; + var outputRows = this.outputShape[0]; + var outputCols = this.outputShape[1]; + var nbPatches = outputRows * outputCols; + var matMul = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [nbPatches, nbFilter]); + + if (this.useBias) { + for (var n = 0; n < nbFilter; n++) { + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assigns(matMul.tensor.pick(null, n), this.weights['bias'].tensor.get(n)); + } + } + + __WEBPACK_IMPORTED_MODULE_7_ndarray_gemm___default()(matMul.tensor, this.imColsMat.tensor, this.wRowsMat.tensor, 1, 1); + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], this.outputShape); + var outputChannelRaveled = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [outputRows * outputCols]); + var outputChannel = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [outputRows, outputCols]); + + for (var _n2 = 0; _n2 < nbFilter; _n2++) { + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assign(outputChannelRaveled.tensor, matMul.tensor.pick(null, _n2)); + outputChannel.replaceTensorData(outputChannelRaveled.tensor.data); + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assign(this.output.tensor.pick(null, null, _n2), outputChannel.tensor); + } + + this.activationFunc(this.output); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + }, { + key: "_createIndexMap", + value: function _createIndexMap(indicesForReshaped) { + if (this.indexMap) { + return; + } + + var _inputShape = _slicedToArray(this.inputShape, 3), + inputRows = _inputShape[0], + inputCols = _inputShape[1], + inputChannels = _inputShape[2]; + + var indices = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */](indicesForReshaped.data, indicesForReshaped.shape, { + type: Int32Array + }); + + if (this.padding === 'same') { + var _inputPadding2 = _slicedToArray(this.inputPadding, 4), + paddingRowBefore = _inputPadding2[0], + paddingRowAfter = _inputPadding2[1], + paddingColBefore = _inputPadding2[2], + paddingColAfter = _inputPadding2[3]; + + inputRows = inputRows + paddingRowBefore + paddingRowAfter; + inputCols = inputCols + paddingColBefore + paddingColAfter; + var padValue = -1; + indices = this._padInput(indices, padValue); + } + + var nbRow = this.kernelShape[1]; + var nbCol = this.kernelShape[2]; + var outputRows = this.outputShape[0]; + var outputCols = this.outputShape[1]; + var nbPatches = outputRows * outputCols; + var patchLen = nbRow * nbCol * inputChannels; + var nbRowDilated = nbRow + (nbRow - 1) * (this.dilationRate[0] - 1); + var nbColDilated = nbCol + (nbCol - 1) * (this.dilationRate[1] - 1); + this.indexMap = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [nbPatches, patchLen], { + type: Int32Array + }); + var indicesPatch = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [nbRow, nbCol, inputChannels]); + var offset = 0; + + for (var i = 0, limit = inputRows - nbRowDilated; i <= limit; i += this.strides[0]) { + for (var j = 0, _limit2 = inputCols - nbColDilated; j <= _limit2; j += this.strides[1]) { + __WEBPACK_IMPORTED_MODULE_6_ndarray_ops___default.a.assign(indicesPatch.tensor, indices.tensor.hi(i + nbRowDilated, j + nbColDilated, inputChannels).lo(i, j, 0).step(this.dilationRate[0], this.dilationRate[1], 1)); + this.indexMap.tensor.data.set(indicesPatch.tensor.data, offset); + offset += patchLen; + } + } + + this.indexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + }, { + key: "_callGPU", + value: function _callGPU(x) { + var outputTextureShape; + + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(x.indicesForReshaped); + + outputTextureShape = [this.indexMap.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } else { + this.inputShape = x.tensor.shape; + + this._calcOutputShape(this.inputShape); + + x = this._padInput(x); + + this._im2col(x); + + this.imColsMat.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + outputTextureShape = [this.imColsMat.glTextureShape[0], this.weights['kernel'].glTextureShape[1]]; + } + + if (this.activation !== 'linear' && !this.outputPreactiv) { + this.outputPreactiv = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], outputTextureShape); + this.outputPreactiv.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.outputPreactiv.is2DReshaped = true; + this.outputPreactiv.originalShape = this.outputShape; + this.outputPreactiv.indicesForReshaped = __WEBPACK_IMPORTED_MODULE_5__utils_tensorUtils__["b" /* createIndicesFor2DReshaped */](this.outputShape, false, -1); + } + + if (!this.output) { + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = __WEBPACK_IMPORTED_MODULE_5__utils_tensorUtils__["b" /* createIndicesFor2DReshaped */](this.outputShape, false, -1); + } + + if (x.is2DReshaped || x.is2DSquareReshaped) { + var hasFragments = Boolean(x.glTextureFragments); + + if (hasFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + } + + if (!this.convProgram) { + var convProgramSource = Object(__WEBPACK_IMPORTED_MODULE_4__webgl_dynamic_createGLSLProgram__["a" /* default */])('conv2d', this.output.glTextureFragmentShape ? this.output.glTextureFragmentShape : this.output.glTextureShape, x.glTextureFragmentShape ? x.glTextureFragmentShape : x.glTextureShape, this.indexMap.glTextureFragmentShape ? this.indexMap.glTextureFragmentShape : this.indexMap.glTextureShape, this.useBias, hasFragments); + this.convProgram = __WEBPACK_IMPORTED_MODULE_3__WebGL2__["b" /* webgl2 */].compileProgram(convProgramSource); + } + + __WEBPACK_IMPORTED_MODULE_3__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.convProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.indexMap, + name: 'indexMap' + }, { + input: this.weights['kernel'], + name: 'kernel' + }].concat(_toConsumableArray(this.useBias ? [{ + input: this.weights['bias'], + name: 'bias' + }] : [])), + supportsTextureFragments: true + }); + + if (hasFragments) { + x.removeGLTextureFragmentsAsColStack(); + } + } else { + var matMulInputs = [{ + input: this.imColsMat, + name: 'A' + }, { + input: this.weights['kernel'], + name: 'B' + }]; + + if (this.useBias) { + matMulInputs.push({ + input: this.weights['bias'], + name: 'C' + }); + } + + __WEBPACK_IMPORTED_MODULE_3__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.matMulProgram, + output: this.activation === 'linear' ? this.output : this.outputPreactiv, + inputs: matMulInputs, + uniforms: [{ + value: this.useBias ? 1 : 0, + type: 'bool', + name: 'addC' + }], + supportsTextureFragments: true + }); + } + + if (this.activation !== 'linear') { + __WEBPACK_IMPORTED_MODULE_3__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.activationProgram, + output: this.output, + inputs: [{ + input: this.outputPreactiv, + name: 'x' + }], + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + }]); + + return Conv2D; +}(__WEBPACK_IMPORTED_MODULE_0__Layer__["a" /* default */]); + + + +/***/ }), +/* 116 */ +/***/ (function(module, exports, __webpack_require__) { + +module.exports = !__webpack_require__(13) && !__webpack_require__(8)(function () { + return Object.defineProperty(__webpack_require__(84)('div'), 'a', { get: function () { return 7; } }).a != 7; +}); + + +/***/ }), +/* 117 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var global = __webpack_require__(6); +var DESCRIPTORS = __webpack_require__(13); +var LIBRARY = __webpack_require__(42); +var $typed = __webpack_require__(85); +var hide = __webpack_require__(16); +var redefineAll = __webpack_require__(43); +var fails = __webpack_require__(8); +var anInstance = __webpack_require__(44); +var toInteger = __webpack_require__(36); +var toLength = __webpack_require__(12); +var toIndex = __webpack_require__(118); +var gOPN = __webpack_require__(55).f; +var dP = __webpack_require__(10).f; +var arrayFill = __webpack_require__(91); +var setToStringTag = __webpack_require__(47); +var ARRAY_BUFFER = 'ArrayBuffer'; +var DATA_VIEW = 'DataView'; +var PROTOTYPE = 'prototype'; +var WRONG_LENGTH = 'Wrong length!'; +var WRONG_INDEX = 'Wrong index!'; +var $ArrayBuffer = global[ARRAY_BUFFER]; +var $DataView = global[DATA_VIEW]; +var Math = global.Math; +var RangeError = global.RangeError; +// eslint-disable-next-line no-shadow-restricted-names +var Infinity = global.Infinity; +var BaseBuffer = $ArrayBuffer; +var abs = Math.abs; +var pow = Math.pow; +var floor = Math.floor; +var log = Math.log; +var LN2 = Math.LN2; +var BUFFER = 'buffer'; +var BYTE_LENGTH = 'byteLength'; +var BYTE_OFFSET = 'byteOffset'; +var $BUFFER = DESCRIPTORS ? '_b' : BUFFER; +var $LENGTH = DESCRIPTORS ? '_l' : BYTE_LENGTH; +var $OFFSET = DESCRIPTORS ? '_o' : BYTE_OFFSET; + +// IEEE754 conversions based on https://github.com/feross/ieee754 +function packIEEE754(value, mLen, nBytes) { + var buffer = Array(nBytes); + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var rt = mLen === 23 ? pow(2, -24) - pow(2, -77) : 0; + var i = 0; + var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0; + var e, m, c; + value = abs(value); + // eslint-disable-next-line no-self-compare + if (value != value || value === Infinity) { + // eslint-disable-next-line no-self-compare + m = value != value ? 1 : 0; + e = eMax; + } else { + e = floor(log(value) / LN2); + if (value * (c = pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * pow(2, mLen); + e = e + eBias; + } else { + m = value * pow(2, eBias - 1) * pow(2, mLen); + e = 0; + } + } + for (; mLen >= 8; buffer[i++] = m & 255, m /= 256, mLen -= 8); + e = e << mLen | m; + eLen += mLen; + for (; eLen > 0; buffer[i++] = e & 255, e /= 256, eLen -= 8); + buffer[--i] |= s * 128; + return buffer; +} +function unpackIEEE754(buffer, mLen, nBytes) { + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var nBits = eLen - 7; + var i = nBytes - 1; + var s = buffer[i--]; + var e = s & 127; + var m; + s >>= 7; + for (; nBits > 0; e = e * 256 + buffer[i], i--, nBits -= 8); + m = e & (1 << -nBits) - 1; + e >>= -nBits; + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[i], i--, nBits -= 8); + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : s ? -Infinity : Infinity; + } else { + m = m + pow(2, mLen); + e = e - eBias; + } return (s ? -1 : 1) * m * pow(2, e - mLen); +} + +function unpackI32(bytes) { + return bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]; +} +function packI8(it) { + return [it & 0xff]; +} +function packI16(it) { + return [it & 0xff, it >> 8 & 0xff]; +} +function packI32(it) { + return [it & 0xff, it >> 8 & 0xff, it >> 16 & 0xff, it >> 24 & 0xff]; +} +function packF64(it) { + return packIEEE754(it, 52, 8); +} +function packF32(it) { + return packIEEE754(it, 23, 4); +} + +function addGetter(C, key, internal) { + dP(C[PROTOTYPE], key, { get: function () { return this[internal]; } }); +} + +function get(view, bytes, index, isLittleEndian) { + var numIndex = +index; + var intIndex = toIndex(numIndex); + if (intIndex + bytes > view[$LENGTH]) throw RangeError(WRONG_INDEX); + var store = view[$BUFFER]._b; + var start = intIndex + view[$OFFSET]; + var pack = store.slice(start, start + bytes); + return isLittleEndian ? pack : pack.reverse(); +} +function set(view, bytes, index, conversion, value, isLittleEndian) { + var numIndex = +index; + var intIndex = toIndex(numIndex); + if (intIndex + bytes > view[$LENGTH]) throw RangeError(WRONG_INDEX); + var store = view[$BUFFER]._b; + var start = intIndex + view[$OFFSET]; + var pack = conversion(+value); + for (var i = 0; i < bytes; i++) store[start + i] = pack[isLittleEndian ? i : bytes - i - 1]; +} + +if (!$typed.ABV) { + $ArrayBuffer = function ArrayBuffer(length) { + anInstance(this, $ArrayBuffer, ARRAY_BUFFER); + var byteLength = toIndex(length); + this._b = arrayFill.call(Array(byteLength), 0); + this[$LENGTH] = byteLength; + }; + + $DataView = function DataView(buffer, byteOffset, byteLength) { + anInstance(this, $DataView, DATA_VIEW); + anInstance(buffer, $ArrayBuffer, DATA_VIEW); + var bufferLength = buffer[$LENGTH]; + var offset = toInteger(byteOffset); + if (offset < 0 || offset > bufferLength) throw RangeError('Wrong offset!'); + byteLength = byteLength === undefined ? bufferLength - offset : toLength(byteLength); + if (offset + byteLength > bufferLength) throw RangeError(WRONG_LENGTH); + this[$BUFFER] = buffer; + this[$OFFSET] = offset; + this[$LENGTH] = byteLength; + }; + + if (DESCRIPTORS) { + addGetter($ArrayBuffer, BYTE_LENGTH, '_l'); + addGetter($DataView, BUFFER, '_b'); + addGetter($DataView, BYTE_LENGTH, '_l'); + addGetter($DataView, BYTE_OFFSET, '_o'); + } + + redefineAll($DataView[PROTOTYPE], { + getInt8: function getInt8(byteOffset) { + return get(this, 1, byteOffset)[0] << 24 >> 24; + }, + getUint8: function getUint8(byteOffset) { + return get(this, 1, byteOffset)[0]; + }, + getInt16: function getInt16(byteOffset /* , littleEndian */) { + var bytes = get(this, 2, byteOffset, arguments[1]); + return (bytes[1] << 8 | bytes[0]) << 16 >> 16; + }, + getUint16: function getUint16(byteOffset /* , littleEndian */) { + var bytes = get(this, 2, byteOffset, arguments[1]); + return bytes[1] << 8 | bytes[0]; + }, + getInt32: function getInt32(byteOffset /* , littleEndian */) { + return unpackI32(get(this, 4, byteOffset, arguments[1])); + }, + getUint32: function getUint32(byteOffset /* , littleEndian */) { + return unpackI32(get(this, 4, byteOffset, arguments[1])) >>> 0; + }, + getFloat32: function getFloat32(byteOffset /* , littleEndian */) { + return unpackIEEE754(get(this, 4, byteOffset, arguments[1]), 23, 4); + }, + getFloat64: function getFloat64(byteOffset /* , littleEndian */) { + return unpackIEEE754(get(this, 8, byteOffset, arguments[1]), 52, 8); + }, + setInt8: function setInt8(byteOffset, value) { + set(this, 1, byteOffset, packI8, value); + }, + setUint8: function setUint8(byteOffset, value) { + set(this, 1, byteOffset, packI8, value); + }, + setInt16: function setInt16(byteOffset, value /* , littleEndian */) { + set(this, 2, byteOffset, packI16, value, arguments[2]); + }, + setUint16: function setUint16(byteOffset, value /* , littleEndian */) { + set(this, 2, byteOffset, packI16, value, arguments[2]); + }, + setInt32: function setInt32(byteOffset, value /* , littleEndian */) { + set(this, 4, byteOffset, packI32, value, arguments[2]); + }, + setUint32: function setUint32(byteOffset, value /* , littleEndian */) { + set(this, 4, byteOffset, packI32, value, arguments[2]); + }, + setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) { + set(this, 4, byteOffset, packF32, value, arguments[2]); + }, + setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) { + set(this, 8, byteOffset, packF64, value, arguments[2]); + } + }); +} else { + if (!fails(function () { + $ArrayBuffer(1); + }) || !fails(function () { + new $ArrayBuffer(-1); // eslint-disable-line no-new + }) || fails(function () { + new $ArrayBuffer(); // eslint-disable-line no-new + new $ArrayBuffer(1.5); // eslint-disable-line no-new + new $ArrayBuffer(NaN); // eslint-disable-line no-new + return $ArrayBuffer.name != ARRAY_BUFFER; + })) { + $ArrayBuffer = function ArrayBuffer(length) { + anInstance(this, $ArrayBuffer); + return new BaseBuffer(toIndex(length)); + }; + var ArrayBufferProto = $ArrayBuffer[PROTOTYPE] = BaseBuffer[PROTOTYPE]; + for (var keys = gOPN(BaseBuffer), j = 0, key; keys.length > j;) { + if (!((key = keys[j++]) in $ArrayBuffer)) hide($ArrayBuffer, key, BaseBuffer[key]); + } + if (!LIBRARY) ArrayBufferProto.constructor = $ArrayBuffer; + } + // iOS Safari 7.x bug + var view = new $DataView(new $ArrayBuffer(2)); + var $setInt8 = $DataView[PROTOTYPE].setInt8; + view.setInt8(0, 2147483648); + view.setInt8(1, 2147483649); + if (view.getInt8(0) || !view.getInt8(1)) redefineAll($DataView[PROTOTYPE], { + setInt8: function setInt8(byteOffset, value) { + $setInt8.call(this, byteOffset, value << 24 >> 24); + }, + setUint8: function setUint8(byteOffset, value) { + $setInt8.call(this, byteOffset, value << 24 >> 24); + } + }, true); +} +setToStringTag($ArrayBuffer, ARRAY_BUFFER); +setToStringTag($DataView, DATA_VIEW); +hide($DataView[PROTOTYPE], $typed.VIEW, true); +exports[ARRAY_BUFFER] = $ArrayBuffer; +exports[DATA_VIEW] = $DataView; + + +/***/ }), +/* 118 */ +/***/ (function(module, exports, __webpack_require__) { + +// https://tc39.github.io/ecma262/#sec-toindex +var toInteger = __webpack_require__(36); +var toLength = __webpack_require__(12); +module.exports = function (it) { + if (it === undefined) return 0; + var number = toInteger(it); + var length = toLength(number); + if (number !== length) throw RangeError('Wrong length!'); + return length; +}; + + +/***/ }), +/* 119 */ +/***/ (function(module, exports, __webpack_require__) { + +var has = __webpack_require__(14); +var toIObject = __webpack_require__(20); +var arrayIndexOf = __webpack_require__(87)(false); +var IE_PROTO = __webpack_require__(88)('IE_PROTO'); + +module.exports = function (object, names) { + var O = toIObject(object); + var i = 0; + var result = []; + var key; + for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (has(O, key = names[i++])) { + ~arrayIndexOf(result, key) || result.push(key); + } + return result; +}; + + +/***/ }), +/* 120 */ +/***/ (function(module, exports, __webpack_require__) { + +var document = __webpack_require__(6).document; +module.exports = document && document.documentElement; + + +/***/ }), +/* 121 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.2.2 IsArray(argument) +var cof = __webpack_require__(45); +module.exports = Array.isArray || function isArray(arg) { + return cof(arg) == 'Array'; +}; + + +/***/ }), +/* 122 */ +/***/ (function(module, exports) { + +module.exports = function (done, value) { + return { value: value, done: !!done }; +}; + + +/***/ }), +/* 123 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var LIBRARY = __webpack_require__(42); +var $export = __webpack_require__(0); +var redefine = __webpack_require__(29); +var hide = __webpack_require__(16); +var has = __webpack_require__(14); +var Iterators = __webpack_require__(48); +var $iterCreate = __webpack_require__(188); +var setToStringTag = __webpack_require__(47); +var getPrototypeOf = __webpack_require__(49); +var ITERATOR = __webpack_require__(9)('iterator'); +var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` +var FF_ITERATOR = '@@iterator'; +var KEYS = 'keys'; +var VALUES = 'values'; + +var returnThis = function () { return this; }; + +module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { + $iterCreate(Constructor, NAME, next); + var getMethod = function (kind) { + if (!BUGGY && kind in proto) return proto[kind]; + switch (kind) { + case KEYS: return function keys() { return new Constructor(this, kind); }; + case VALUES: return function values() { return new Constructor(this, kind); }; + } return function entries() { return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator'; + var DEF_VALUES = DEFAULT == VALUES; + var VALUES_BUG = false; + var proto = Base.prototype; + var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; + var $default = $native || getMethod(DEFAULT); + var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; + var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; + var methods, key, IteratorPrototype; + // Fix native + if ($anyNative) { + IteratorPrototype = getPrototypeOf($anyNative.call(new Base())); + if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { + // Set @@toStringTag to native iterators + setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if (!LIBRARY && !has(IteratorPrototype, ITERATOR)) hide(IteratorPrototype, ITERATOR, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if (DEF_VALUES && $native && $native.name !== VALUES) { + VALUES_BUG = true; + $default = function values() { return $native.call(this); }; + } + // Define iterator + if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) { + hide(proto, ITERATOR, $default); + } + // Plug for library + Iterators[NAME] = $default; + Iterators[TAG] = returnThis; + if (DEFAULT) { + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if (FORCED) for (key in methods) { + if (!(key in proto)) redefine(proto, key, methods[key]); + } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; +}; + + +/***/ }), +/* 124 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length) + +var toObject = __webpack_require__(24); +var toAbsoluteIndex = __webpack_require__(46); +var toLength = __webpack_require__(12); + +module.exports = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) { + var O = toObject(this); + var len = toLength(O.length); + var to = toAbsoluteIndex(target, len); + var from = toAbsoluteIndex(start, len); + var end = arguments.length > 2 ? arguments[2] : undefined; + var count = Math.min((end === undefined ? len : toAbsoluteIndex(end, len)) - from, len - to); + var inc = 1; + if (from < to && to < from + count) { + inc = -1; + from += count - 1; + to += count - 1; + } + while (count-- > 0) { + if (from in O) O[to] = O[from]; + else delete O[to]; + to += inc; + from += inc; + } return O; +}; + + +/***/ }), +/* 125 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var dP = __webpack_require__(10).f; +var create = __webpack_require__(56); +var redefineAll = __webpack_require__(43); +var ctx = __webpack_require__(23); +var anInstance = __webpack_require__(44); +var forOf = __webpack_require__(70); +var $iterDefine = __webpack_require__(123); +var step = __webpack_require__(122); +var setSpecies = __webpack_require__(68); +var DESCRIPTORS = __webpack_require__(13); +var fastKey = __webpack_require__(31).fastKey; +var validate = __webpack_require__(51); +var SIZE = DESCRIPTORS ? '_s' : 'size'; + +var getEntry = function (that, key) { + // fast case + var index = fastKey(key); + var entry; + if (index !== 'F') return that._i[index]; + // frozen object case + for (entry = that._f; entry; entry = entry.n) { + if (entry.k == key) return entry; + } +}; + +module.exports = { + getConstructor: function (wrapper, NAME, IS_MAP, ADDER) { + var C = wrapper(function (that, iterable) { + anInstance(that, C, NAME, '_i'); + that._t = NAME; // collection type + that._i = create(null); // index + that._f = undefined; // first entry + that._l = undefined; // last entry + that[SIZE] = 0; // size + if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that); + }); + redefineAll(C.prototype, { + // 23.1.3.1 Map.prototype.clear() + // 23.2.3.2 Set.prototype.clear() + clear: function clear() { + for (var that = validate(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) { + entry.r = true; + if (entry.p) entry.p = entry.p.n = undefined; + delete data[entry.i]; + } + that._f = that._l = undefined; + that[SIZE] = 0; + }, + // 23.1.3.3 Map.prototype.delete(key) + // 23.2.3.4 Set.prototype.delete(value) + 'delete': function (key) { + var that = validate(this, NAME); + var entry = getEntry(that, key); + if (entry) { + var next = entry.n; + var prev = entry.p; + delete that._i[entry.i]; + entry.r = true; + if (prev) prev.n = next; + if (next) next.p = prev; + if (that._f == entry) that._f = next; + if (that._l == entry) that._l = prev; + that[SIZE]--; + } return !!entry; + }, + // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined) + // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined) + forEach: function forEach(callbackfn /* , that = undefined */) { + validate(this, NAME); + var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3); + var entry; + while (entry = entry ? entry.n : this._f) { + f(entry.v, entry.k, this); + // revert to the last existing entry + while (entry && entry.r) entry = entry.p; + } + }, + // 23.1.3.7 Map.prototype.has(key) + // 23.2.3.7 Set.prototype.has(value) + has: function has(key) { + return !!getEntry(validate(this, NAME), key); + } + }); + if (DESCRIPTORS) dP(C.prototype, 'size', { + get: function () { + return validate(this, NAME)[SIZE]; + } + }); + return C; + }, + def: function (that, key, value) { + var entry = getEntry(that, key); + var prev, index; + // change existing entry + if (entry) { + entry.v = value; + // create new entry + } else { + that._l = entry = { + i: index = fastKey(key, true), // <- index + k: key, // <- key + v: value, // <- value + p: prev = that._l, // <- previous entry + n: undefined, // <- next entry + r: false // <- removed + }; + if (!that._f) that._f = entry; + if (prev) prev.n = entry; + that[SIZE]++; + // add to index + if (index !== 'F') that._i[index] = entry; + } return that; + }, + getEntry: getEntry, + setStrong: function (C, NAME, IS_MAP) { + // add .keys, .values, .entries, [@@iterator] + // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11 + $iterDefine(C, NAME, function (iterated, kind) { + this._t = validate(iterated, NAME); // target + this._k = kind; // kind + this._l = undefined; // previous + }, function () { + var that = this; + var kind = that._k; + var entry = that._l; + // revert to the last existing entry + while (entry && entry.r) entry = entry.p; + // get next entry + if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) { + // or finish the iteration + that._t = undefined; + return step(1); + } + // return step by kind + if (kind == 'keys') return step(0, entry.k); + if (kind == 'values') return step(0, entry.v); + return step(0, [entry.k, entry.v]); + }, IS_MAP ? 'entries' : 'values', !IS_MAP, true); + + // add [@@species], 23.1.2.2, 23.2.2.2 + setSpecies(NAME); + } +}; + + +/***/ }), +/* 126 */ +/***/ (function(module, exports, __webpack_require__) { + +// call something on iterator step with safe closing on error +var anObject = __webpack_require__(7); +module.exports = function (iterator, fn, value, entries) { + try { + return entries ? fn(anObject(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch (e) { + var ret = iterator['return']; + if (ret !== undefined) anObject(ret.call(iterator)); + throw e; + } +}; + + +/***/ }), +/* 127 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// 19.1.2.1 Object.assign(target, source, ...) +var getKeys = __webpack_require__(37); +var gOPS = __webpack_require__(72); +var pIE = __webpack_require__(58); +var toObject = __webpack_require__(24); +var IObject = __webpack_require__(86); +var $assign = Object.assign; + +// should work with symbols and should have deterministic property order (V8 bug) +module.exports = !$assign || __webpack_require__(8)(function () { + var A = {}; + var B = {}; + // eslint-disable-next-line no-undef + var S = Symbol(); + var K = 'abcdefghijklmnopqrst'; + A[S] = 7; + K.split('').forEach(function (k) { B[k] = k; }); + return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; +}) ? function assign(target, source) { // eslint-disable-line no-unused-vars + var T = toObject(target); + var aLen = arguments.length; + var index = 1; + var getSymbols = gOPS.f; + var isEnum = pIE.f; + while (aLen > index) { + var S = IObject(arguments[index++]); + var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S); + var length = keys.length; + var j = 0; + var key; + while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key]; + } return T; +} : $assign; + + +/***/ }), +/* 128 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var redefineAll = __webpack_require__(43); +var getWeak = __webpack_require__(31).getWeak; +var anObject = __webpack_require__(7); +var isObject = __webpack_require__(5); +var anInstance = __webpack_require__(44); +var forOf = __webpack_require__(70); +var createArrayMethod = __webpack_require__(57); +var $has = __webpack_require__(14); +var validate = __webpack_require__(51); +var arrayFind = createArrayMethod(5); +var arrayFindIndex = createArrayMethod(6); +var id = 0; + +// fallback for uncaught frozen keys +var uncaughtFrozenStore = function (that) { + return that._l || (that._l = new UncaughtFrozenStore()); +}; +var UncaughtFrozenStore = function () { + this.a = []; +}; +var findUncaughtFrozen = function (store, key) { + return arrayFind(store.a, function (it) { + return it[0] === key; + }); +}; +UncaughtFrozenStore.prototype = { + get: function (key) { + var entry = findUncaughtFrozen(this, key); + if (entry) return entry[1]; + }, + has: function (key) { + return !!findUncaughtFrozen(this, key); + }, + set: function (key, value) { + var entry = findUncaughtFrozen(this, key); + if (entry) entry[1] = value; + else this.a.push([key, value]); + }, + 'delete': function (key) { + var index = arrayFindIndex(this.a, function (it) { + return it[0] === key; + }); + if (~index) this.a.splice(index, 1); + return !!~index; + } +}; + +module.exports = { + getConstructor: function (wrapper, NAME, IS_MAP, ADDER) { + var C = wrapper(function (that, iterable) { + anInstance(that, C, NAME, '_i'); + that._t = NAME; // collection type + that._i = id++; // collection id + that._l = undefined; // leak store for uncaught frozen objects + if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that); + }); + redefineAll(C.prototype, { + // 23.3.3.2 WeakMap.prototype.delete(key) + // 23.4.3.3 WeakSet.prototype.delete(value) + 'delete': function (key) { + if (!isObject(key)) return false; + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key); + return data && $has(data, this._i) && delete data[this._i]; + }, + // 23.3.3.4 WeakMap.prototype.has(key) + // 23.4.3.4 WeakSet.prototype.has(value) + has: function has(key) { + if (!isObject(key)) return false; + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key); + return data && $has(data, this._i); + } + }); + return C; + }, + def: function (that, key, value) { + var data = getWeak(anObject(key), true); + if (data === true) uncaughtFrozenStore(that).set(key, value); + else data[that._i] = value; + return that; + }, + ufstore: uncaughtFrozenStore +}; + + +/***/ }), +/* 129 */ +/***/ (function(module, exports) { + +// fast apply, http://jsperf.lnkit.com/fast-apply/5 +module.exports = function (fn, args, that) { + var un = that === undefined; + switch (args.length) { + case 0: return un ? fn() + : fn.call(that); + case 1: return un ? fn(args[0]) + : fn.call(that, args[0]); + case 2: return un ? fn(args[0], args[1]) + : fn.call(that, args[0], args[1]); + case 3: return un ? fn(args[0], args[1], args[2]) + : fn.call(that, args[0], args[1], args[2]); + case 4: return un ? fn(args[0], args[1], args[2], args[3]) + : fn.call(that, args[0], args[1], args[2], args[3]); + } return fn.apply(that, args); +}; + + +/***/ }), +/* 130 */ +/***/ (function(module, exports, __webpack_require__) { + +// all object keys, includes non-enumerable and symbols +var gOPN = __webpack_require__(55); +var gOPS = __webpack_require__(72); +var anObject = __webpack_require__(7); +var Reflect = __webpack_require__(6).Reflect; +module.exports = Reflect && Reflect.ownKeys || function ownKeys(it) { + var keys = gOPN.f(anObject(it)); + var getSymbols = gOPS.f; + return getSymbols ? keys.concat(getSymbols(it)) : keys; +}; + + +/***/ }), +/* 131 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// 25.4.1.5 NewPromiseCapability(C) +var aFunction = __webpack_require__(35); + +function PromiseCapability(C) { + var resolve, reject; + this.promise = new C(function ($$resolve, $$reject) { + if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor'); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = aFunction(resolve); + this.reject = aFunction(reject); +} + +module.exports.f = function (C) { + return new PromiseCapability(C); +}; + + +/***/ }), +/* 132 */ +/***/ (function(module, exports, __webpack_require__) { + +exports.f = __webpack_require__(9); + + +/***/ }), +/* 133 */ +/***/ (function(module, exports, __webpack_require__) { + +// fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window +var toIObject = __webpack_require__(20); +var gOPN = __webpack_require__(55).f; +var toString = {}.toString; + +var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames + ? Object.getOwnPropertyNames(window) : []; + +var getWindowNames = function (it) { + try { + return gOPN(it); + } catch (e) { + return windowNames.slice(); + } +}; + +module.exports.f = function getOwnPropertyNames(it) { + return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it)); +}; + + +/***/ }), +/* 134 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var toInteger = __webpack_require__(36); +var defined = __webpack_require__(30); + +module.exports = function repeat(count) { + var str = String(defined(this)); + var res = ''; + var n = toInteger(count); + if (n < 0 || n == Infinity) throw RangeError("Count can't be negative"); + for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) res += str; + return res; +}; + + +/***/ }), +/* 135 */ +/***/ (function(module, exports, __webpack_require__) { + +// 7.2.8 IsRegExp(argument) +var isObject = __webpack_require__(5); +var cof = __webpack_require__(45); +var MATCH = __webpack_require__(9)('match'); +module.exports = function (it) { + var isRegExp; + return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp'); +}; + + +/***/ }), +/* 136 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.3 Number.isInteger(number) +var isObject = __webpack_require__(5); +var floor = Math.floor; +module.exports = function isInteger(it) { + return !isObject(it) && isFinite(it) && floor(it) === it; +}; + + +/***/ }), +/* 137 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(0); +var defined = __webpack_require__(30); +var fails = __webpack_require__(8); +var spaces = __webpack_require__(102); +var space = '[' + spaces + ']'; +var non = '\u200b\u0085'; +var ltrim = RegExp('^' + space + space + '*'); +var rtrim = RegExp(space + space + '*$'); + +var exporter = function (KEY, exec, ALIAS) { + var exp = {}; + var FORCE = fails(function () { + return !!spaces[KEY]() || non[KEY]() != non; + }); + var fn = exp[KEY] = FORCE ? exec(trim) : spaces[KEY]; + if (ALIAS) exp[ALIAS] = fn; + $export($export.P + $export.F * FORCE, 'String', exp); +}; + +// 1 -> String#trimLeft +// 2 -> String#trimRight +// 3 -> String#trim +var trim = exporter.trim = function (string, TYPE) { + string = String(defined(string)); + if (TYPE & 1) string = string.replace(ltrim, ''); + if (TYPE & 2) string = string.replace(rtrim, ''); + return string; +}; + +module.exports = exporter; + + +/***/ }), +/* 138 */ +/***/ (function(module, exports) { + +// 20.2.2.20 Math.log1p(x) +module.exports = Math.log1p || function log1p(x) { + return (x = +x) > -1e-8 && x < 1e-8 ? x - x * x / 2 : Math.log(1 + x); +}; + + +/***/ }), +/* 139 */ +/***/ (function(module, exports, __webpack_require__) { + +var getKeys = __webpack_require__(37); +var toIObject = __webpack_require__(20); +var isEnum = __webpack_require__(58).f; +module.exports = function (isEntries) { + return function (it) { + var O = toIObject(it); + var keys = getKeys(O); + var length = keys.length; + var i = 0; + var result = []; + var key; + while (length > i) if (isEnum.call(O, key = keys[i++])) { + result.push(isEntries ? [key, O[key]] : O[key]); + } return result; + }; +}; + + +/***/ }), +/* 140 */ +/***/ (function(module, exports, __webpack_require__) { + +// https://github.com/tc39/proposal-string-pad-start-end +var toLength = __webpack_require__(12); +var repeat = __webpack_require__(134); +var defined = __webpack_require__(30); + +module.exports = function (that, maxLength, fillString, left) { + var S = String(defined(that)); + var stringLength = S.length; + var fillStr = fillString === undefined ? ' ' : String(fillString); + var intMaxLength = toLength(maxLength); + if (intMaxLength <= stringLength || fillStr == '') return S; + var fillLen = intMaxLength - stringLength; + var stringFiller = repeat.call(fillStr, Math.ceil(fillLen / fillStr.length)); + if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen); + return left ? stringFiller + S : S + stringFiller; +}; + + +/***/ }), +/* 141 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +module.exports = freeGlobal; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(38))) + +/***/ }), +/* 142 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(22), + stubFalse = __webpack_require__(303); + +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; + +/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ +var isBuffer = nativeIsBuffer || stubFalse; + +module.exports = isBuffer; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(74)(module))) + +/***/ }), +/* 143 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsTypedArray = __webpack_require__(304), + baseUnary = __webpack_require__(305), + nodeUtil = __webpack_require__(306); + +/* Node.js helper references. */ +var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + +/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ +var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + +module.exports = isTypedArray; + + +/***/ }), +/* 144 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseGetTag = __webpack_require__(60), + isObject = __webpack_require__(64); + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +module.exports = isFunction; + + +/***/ }), +/* 145 */ +/***/ (function(module, exports, __webpack_require__) { + +var ListCache = __webpack_require__(76), + stackClear = __webpack_require__(317), + stackDelete = __webpack_require__(318), + stackGet = __webpack_require__(319), + stackHas = __webpack_require__(320), + stackSet = __webpack_require__(321); + +/** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; +} + +// Add methods to `Stack`. +Stack.prototype.clear = stackClear; +Stack.prototype['delete'] = stackDelete; +Stack.prototype.get = stackGet; +Stack.prototype.has = stackHas; +Stack.prototype.set = stackSet; + +module.exports = Stack; + + +/***/ }), +/* 146 */ +/***/ (function(module, exports) { + +/** Used for built-in method references. */ +var funcProto = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; +} + +module.exports = toSource; + + +/***/ }), +/* 147 */ +/***/ (function(module, exports, __webpack_require__) { + +var SetCache = __webpack_require__(338), + arraySome = __webpack_require__(341), + cacheHas = __webpack_require__(342); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ +function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked && stack.get(other)) { + return stacked == other; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; +} + +module.exports = equalArrays; + + +/***/ }), +/* 148 */ +/***/ (function(module, exports) { + +/** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +module.exports = arrayPush; + + +/***/ }), +/* 149 */ +/***/ (function(module, exports) { + +/** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function arrayMap(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} + +module.exports = arrayMap; + + +/***/ }), +/* 150 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(64); + +/** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ +function isStrictComparable(value) { + return value === value && !isObject(value); +} + +module.exports = isStrictComparable; + + +/***/ }), +/* 151 */ +/***/ (function(module, exports) { + +/** + * A specialized version of `matchesProperty` for source values suitable + * for strict equality comparisons, i.e. `===`. + * + * @private + * @param {string} key The key of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ +function matchesStrictComparable(key, srcValue) { + return function(object) { + if (object == null) { + return false; + } + return object[key] === srcValue && + (srcValue !== undefined || (key in Object(object))); + }; +} + +module.exports = matchesStrictComparable; + + +/***/ }), +/* 152 */ +/***/ (function(module, exports, __webpack_require__) { + +var castPath = __webpack_require__(153), + toKey = __webpack_require__(82); + +/** + * The base implementation of `_.get` without support for default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @returns {*} Returns the resolved value. + */ +function baseGet(object, path) { + path = castPath(path, object); + + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = object[toKey(path[index++])]; + } + return (index && index == length) ? object : undefined; +} + +module.exports = baseGet; + + +/***/ }), +/* 153 */ +/***/ (function(module, exports, __webpack_require__) { + +var isArray = __webpack_require__(17), + isKey = __webpack_require__(112), + stringToPath = __webpack_require__(364), + toString = __webpack_require__(367); + +/** + * Casts `value` to a path array if it's not one. + * + * @private + * @param {*} value The value to inspect. + * @param {Object} [object] The object to query keys on. + * @returns {Array} Returns the cast property path array. + */ +function castPath(value, object) { + if (isArray(value)) { + return value; + } + return isKey(value, object) ? [value] : stringToPath(toString(value)); +} + +module.exports = castPath; + + +/***/ }), +/* 154 */ +/***/ (function(module, exports) { + +/** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ +function identity(value) { + return value; +} + +module.exports = identity; + + +/***/ }), +/* 155 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseForOwn = __webpack_require__(376), + createBaseEach = __webpack_require__(379); + +/** + * The base implementation of `_.forEach` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object} Returns `collection`. + */ +var baseEach = createBaseEach(baseForOwn); + +module.exports = baseEach; + + +/***/ }), +/* 156 */ +/***/ (function(module, exports, __webpack_require__) { + +var eq = __webpack_require__(109), + isArrayLike = __webpack_require__(63), + isIndex = __webpack_require__(106), + isObject = __webpack_require__(64); + +/** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ +function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; +} + +module.exports = isIterateeCall; + + +/***/ }), +/* 157 */ +/***/ (function(module, exports, __webpack_require__) { + +var toFinite = __webpack_require__(158); + +/** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ +function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; +} + +module.exports = toInteger; + + +/***/ }), +/* 158 */ +/***/ (function(module, exports, __webpack_require__) { + +var toNumber = __webpack_require__(387); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0, + MAX_INTEGER = 1.7976931348623157e+308; + +/** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ +function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; +} + +module.exports = toFinite; + + +/***/ }), +/* 159 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = function bind(fn, thisArg) { + return function wrap() { + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; + } + return fn.apply(thisArg, args); + }; +}; + + +/***/ }), +/* 160 */ +/***/ (function(module, exports) { + +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @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)) +} + + +/***/ }), +/* 161 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(process) { + +var utils = __webpack_require__(15); +var settle = __webpack_require__(395); +var buildURL = __webpack_require__(397); +var parseHeaders = __webpack_require__(398); +var isURLSameOrigin = __webpack_require__(399); +var createError = __webpack_require__(162); +var btoa = (typeof window !== 'undefined' && window.btoa && window.btoa.bind(window)) || __webpack_require__(400); + +module.exports = function xhrAdapter(config) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + var requestData = config.data; + var requestHeaders = config.headers; + + if (utils.isFormData(requestData)) { + delete requestHeaders['Content-Type']; // Let the browser set it + } + + var request = new XMLHttpRequest(); + var loadEvent = 'onreadystatechange'; + var xDomain = false; + + // For IE 8/9 CORS support + // Only supports POST and GET calls and doesn't returns the response headers. + // DON'T do this for testing b/c XMLHttpRequest is mocked, not XDomainRequest. + if (process.env.NODE_ENV !== 'test' && + typeof window !== 'undefined' && + window.XDomainRequest && !('withCredentials' in request) && + !isURLSameOrigin(config.url)) { + request = new window.XDomainRequest(); + loadEvent = 'onload'; + xDomain = true; + request.onprogress = function handleProgress() {}; + request.ontimeout = function handleTimeout() {}; + } + + // HTTP basic authentication + if (config.auth) { + var username = config.auth.username || ''; + var password = config.auth.password || ''; + requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password); + } + + request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true); + + // Set the request timeout in MS + request.timeout = config.timeout; + + // Listen for ready state + request[loadEvent] = function handleLoad() { + if (!request || (request.readyState !== 4 && !xDomain)) { + return; + } + + // The request errored out and we didn't get a response, this will be + // handled by onerror instead + // With one exception: request that using file: protocol, most browsers + // will return status as 0 even though it's a successful request + if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { + return; + } + + // Prepare the response + var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; + var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; + var response = { + data: responseData, + // IE sends 1223 instead of 204 (https://github.com/axios/axios/issues/201) + status: request.status === 1223 ? 204 : request.status, + statusText: request.status === 1223 ? 'No Content' : request.statusText, + headers: responseHeaders, + config: config, + request: request + }; + + settle(resolve, reject, response); + + // Clean up request + request = null; + }; + + // Handle low level network errors + request.onerror = function handleError() { + // Real errors are hidden from us by the browser + // onerror should only fire if it's a network error + reject(createError('Network Error', config, null, request)); + + // Clean up request + request = null; + }; + + // Handle timeout + request.ontimeout = function handleTimeout() { + reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', + request)); + + // Clean up request + request = null; + }; + + // Add xsrf header + // This is only done if running in a standard browser environment. + // Specifically not if we're in a web worker, or react-native. + if (utils.isStandardBrowserEnv()) { + var cookies = __webpack_require__(401); + + // Add xsrf header + var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ? + cookies.read(config.xsrfCookieName) : + undefined; + + if (xsrfValue) { + requestHeaders[config.xsrfHeaderName] = xsrfValue; + } + } + + // Add headers to the request + if ('setRequestHeader' in request) { + utils.forEach(requestHeaders, function setRequestHeader(val, key) { + if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') { + // Remove Content-Type if data is undefined + delete requestHeaders[key]; + } else { + // Otherwise add header to the request + request.setRequestHeader(key, val); + } + }); + } + + // Add withCredentials to request if needed + if (config.withCredentials) { + request.withCredentials = true; + } + + // Add responseType to request if needed + if (config.responseType) { + try { + request.responseType = config.responseType; + } catch (e) { + // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. + // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. + if (config.responseType !== 'json') { + throw e; + } + } + } + + // Handle progress if needed + if (typeof config.onDownloadProgress === 'function') { + request.addEventListener('progress', config.onDownloadProgress); + } + + // Not all browsers support upload events + if (typeof config.onUploadProgress === 'function' && request.upload) { + request.upload.addEventListener('progress', config.onUploadProgress); + } + + if (config.cancelToken) { + // Handle cancellation + config.cancelToken.promise.then(function onCanceled(cancel) { + if (!request) { + return; + } + + request.abort(); + reject(cancel); + // Clean up request + request = null; + }); + } + + if (requestData === undefined) { + requestData = null; + } + + // Send the request + request.send(requestData); + }); +}; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(65))) + +/***/ }), +/* 162 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var enhanceError = __webpack_require__(396); + +/** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {Object} config The config. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * @returns {Error} The created error. + */ +module.exports = function createError(message, config, code, request, response) { + var error = new Error(message); + return enhanceError(error, config, code, request, response); +}; + + +/***/ }), +/* 163 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = function isCancel(value) { + return !!(value && value.__CANCEL__); +}; + + +/***/ }), +/* 164 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +/** + * A `Cancel` is an object that is thrown when an operation is canceled. + * + * @class + * @param {string=} message The message. + */ +function Cancel(message) { + this.message = message; +} + +Cancel.prototype.toString = function toString() { + return 'Cancel' + (this.message ? ': ' + this.message : ''); +}; + +Cancel.prototype.__CANCEL__ = true; + +module.exports = Cancel; + + +/***/ }), +/* 165 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var createThunk = __webpack_require__(414) + +function Procedure() { + this.argTypes = [] + this.shimArgs = [] + this.arrayArgs = [] + this.arrayBlockIndices = [] + this.scalarArgs = [] + this.offsetArgs = [] + this.offsetArgIndex = [] + this.indexArgs = [] + this.shapeArgs = [] + this.funcName = "" + this.pre = null + this.body = null + this.post = null + this.debug = false +} + +function compileCwise(user_args) { + //Create procedure + var proc = new Procedure() + + //Parse blocks + proc.pre = user_args.pre + proc.body = user_args.body + proc.post = user_args.post + + //Parse arguments + var proc_args = user_args.args.slice(0) + proc.argTypes = proc_args + for(var i=0; i0) { + throw new Error("cwise: pre() block may not reference array args") + } + if(i < proc.post.args.length && proc.post.args[i].count>0) { + throw new Error("cwise: post() block may not reference array args") + } + } else if(arg_type === "scalar") { + proc.scalarArgs.push(i) + proc.shimArgs.push("scalar" + i) + } else if(arg_type === "index") { + proc.indexArgs.push(i) + if(i < proc.pre.args.length && proc.pre.args[i].count > 0) { + throw new Error("cwise: pre() block may not reference array index") + } + if(i < proc.body.args.length && proc.body.args[i].lvalue) { + throw new Error("cwise: body() block may not write to array index") + } + if(i < proc.post.args.length && proc.post.args[i].count > 0) { + throw new Error("cwise: post() block may not reference array index") + } + } else if(arg_type === "shape") { + proc.shapeArgs.push(i) + if(i < proc.pre.args.length && proc.pre.args[i].lvalue) { + throw new Error("cwise: pre() block may not write to array shape") + } + if(i < proc.body.args.length && proc.body.args[i].lvalue) { + throw new Error("cwise: body() block may not write to array shape") + } + if(i < proc.post.args.length && proc.post.args[i].lvalue) { + throw new Error("cwise: post() block may not write to array shape") + } + } else if(typeof arg_type === "object" && arg_type.offset) { + proc.argTypes[i] = "offset" + proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset }) + proc.offsetArgIndex.push(i) + } else { + throw new Error("cwise: Unknown argument type " + proc_args[i]) + } + } + + //Make sure at least one array argument was specified + if(proc.arrayArgs.length <= 0) { + throw new Error("cwise: No array arguments specified") + } + + //Make sure arguments are correct + if(proc.pre.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in pre() block") + } + if(proc.body.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in body() block") + } + if(proc.post.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in post() block") + } + + //Check debug flag + proc.debug = !!user_args.printCode || !!user_args.debug + + //Retrieve name + proc.funcName = user_args.funcName || "cwise" + + //Read in block size + proc.blockSize = user_args.blockSize || 64 + + return createThunk(proc) +} + +module.exports = compileCwise + + +/***/ }), +/* 166 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +function unique_pred(list, compare) { + var ptr = 1 + , len = list.length + , a=list[0], b=list[0] + for(var i=1; i 20 + */ +function sum(array) { + return (array && array.length) + ? baseSum(array, identity) + : 0; +} + +module.exports = sum; + + +/***/ }), +/* 169 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var ndarray = __webpack_require__(66) + +module.exports = unsqueeze + +function unsqueeze (a, axis) { + var shape, stride + + if (axis !== undefined && (!Number.isFinite(axis) || (axis % 1 !== axis))) { + throw new Error('axis of dimension to unsqueeze must be an integer') + } + axis = axis === undefined ? a.shape.length : axis + + shape = a.shape.slice(0) + stride = a.stride.slice(0) + shape.splice(axis || 0, 0, 1) + stride.splice(axis || 0, 0, (stride[axis] || 1) * (shape[axis + 1] || 1)) + + return ndarray(a.data, shape, stride, a.offset) +} + + +/***/ }), +/* 170 */ +/***/ (function(module, exports) { + +/** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ +function last(array) { + var length = array == null ? 0 : array.length; + return length ? array[length - 1] : undefined; +} + +module.exports = last; + + +/***/ }), +/* 171 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var ndarray = __webpack_require__(66) +var ops = __webpack_require__(4) +var pool = __webpack_require__(498) + +function clone(array) { + var dtype = array.dtype + if(dtype === "generic" || dtype === "array") { + dtype = "double" + } + var data = pool.malloc(array.size, dtype) + var result = ndarray(data, array.shape) + ops.assign(result, array) + return result +} +exports.clone = clone + +function malloc(shape, dtype) { + if(!dtype) { + dtype = "double" + } + var sz = 1 + var stride = new Array(shape.length) + for(var i=shape.length-1; i>=0; --i) { + stride[i] = sz + sz *= shape[i] + } + return ndarray(pool.malloc(sz, dtype), shape, stride, 0) +} +exports.malloc = malloc + +function free(array) { + if(array.dtype === "generic" || array.dtype === "array") { + return + } + pool.free(array.data) +} +exports.free = free + +function zeros(shape, dtype) { + if(!dtype) { + dtype = "double" + } + + var sz = 1 + var stride = new Array(shape.length) + for(var i=shape.length-1; i>=0; --i) { + stride[i] = sz + sz *= shape[i] + } + var buf = pool.malloc(sz, dtype) + for(var i=0; i=0; --i) { + stride[i] = sz + sz *= shape[i] + } + var buf = pool.malloc(sz, dtype) + for(var i=0; i=0; --i) { + stride[i] = sz + sz *= shape[i] + } + var buf = pool.malloc(sz, dtype) + for(i=0; i=0; i--) { + offsum += stride[i] + mindim = Math.min(mindim,shape[i]) + } + for(i=0,offset=0; i 0) { + return dupe_number(count|0, value) + } + break + case "object": + if(typeof (count.length) === "number") { + return dupe_array(count, value, 0) + } + break + } + return [] +} + +module.exports = dupe + +/***/ }), +/* 173 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _Pooling1D; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Layer__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_ndarray_ops__); +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } 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 poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +var poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +var _Pooling1D = function (_Layer) { + _inherits(_Pooling1D, _Layer); + + function _Pooling1D() { + var _this; + + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, _Pooling1D); + + _this = _possibleConstructorReturn(this, (_Pooling1D.__proto__ || Object.getPrototypeOf(_Pooling1D)).call(this, attrs)); + _this.layerClass = '_Pooling1D'; + var _attrs$pool_size = attrs.pool_size, + pool_size = _attrs$pool_size === void 0 ? 2 : _attrs$pool_size, + _attrs$strides = attrs.strides, + strides = _attrs$strides === void 0 ? null : _attrs$strides, + _attrs$padding = attrs.padding, + padding = _attrs$padding === void 0 ? 'valid' : _attrs$padding; + _this.poolSize = pool_size; + _this.strides = strides === null ? _this.poolSize : strides; + _this.padding = padding; + _this.poolingFunc = 'max'; + + if (_this.gpu) { + _this.poolingProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingProgramSource); + _this.poolingFragmentsProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingFragmentsProgramSource); + } + + return _this; + } + + _createClass(_Pooling1D, [{ + key: "call", + value: function call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + }, { + key: "_callCPU", + value: function _callCPU(x) { + var stepsNew = this.padding === 'valid' ? Math.floor((x.tensor.shape[0] - this.poolSize + this.strides) / this.strides) : Math.floor((x.tensor.shape[0] + this.strides - 1) / this.strides); + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [stepsNew, x.tensor.shape[1]]); + var outputStep = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [x.tensor.shape[1]]); + var step = this.padding === 'valid' ? 0 : Math.min(0, Math.ceil((x.tensor.shape[0] - (stepsNew - 1) * this.strides - this.poolSize) / 2)); + + for (var i = 0; i < stepsNew; i++) { + var _step = Math.max(0, step); + + var limit = this.poolSize + Math.min(0, step); + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.assign(outputStep.tensor, x.tensor.pick(_step, null)); + var count = 1; + + for (var j = 1; j < limit; j++) { + if (_step + j > x.tensor.shape[0] - 1) { + break; + } + + if (this.poolingFunc === 'max') { + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.maxeq(outputStep.tensor, x.tensor.pick(_step + j, null)); + } else if (this.poolingFunc === 'average') { + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.addeq(outputStep.tensor, x.tensor.pick(_step + j, null)); + } + + count += 1; + } + + if (this.poolingFunc === 'average') { + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.divseq(outputStep.tensor, count); + } + + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.assign(this.output.tensor.pick(i, null), outputStep.tensor); + step += this.strides; + } + } + }, { + key: "_createIndexMap", + value: function _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + var stepsNew = this.padding === 'valid' ? Math.floor((this.inputShape[0] - this.poolSize + this.strides) / this.strides) : Math.floor((this.inputShape[0] + this.strides - 1) / this.strides); + this.outputShape = [stepsNew, this.inputShape[1]]; + this.poolIndexMap = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [stepsNew, this.poolSize], { + type: Int32Array + }); + __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.assigns(this.poolIndexMap.tensor, -1); + var step = this.padding === 'valid' ? 0 : Math.min(0, Math.ceil((this.inputShape[0] - (stepsNew - 1) * this.strides - this.poolSize) / 2)); + + for (var i = 0; i < stepsNew; i++) { + var _step = Math.max(0, step); + + var limit = this.poolSize + Math.min(0, step); + var inputIndex = _step; + this.poolIndexMap.tensor.set(i, 0, inputIndex); + + for (var j = 1; j < limit; j++) { + inputIndex = _step + j; + + if (inputIndex <= this.inputShape[0] - 1) { + this.poolIndexMap.tensor.set(i, j, inputIndex); + } else { + break; + } + } + + step += this.strides; + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + }, { + key: "_callGPU", + value: function _callGPU(x) { + if (!x.glTexture && !x.glTextureFragments) { + x.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this.inputShape = x.tensor.shape; + + this._createIndexMap(); + + if (!this.output) { + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], this.outputShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + var isMaxPooling = this.poolingFunc === 'max'; + var programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: this.poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (x.glTextureFragments) { + x.convert2DRowFragmentedGLTextureToColStack(); + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + x.removeGLTextureFragmentsAsColStack(); + } else { + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + }]); + + return _Pooling1D; +}(__WEBPACK_IMPORTED_MODULE_0__Layer__["a" /* default */]); + + + +/***/ }), +/* 174 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _Pooling2D; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Layer__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__utils_tensorUtils__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_ndarray_ops__); +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +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"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _slicedToArray(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"); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } 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 poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +var poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +var _Pooling2D = function (_Layer) { + _inherits(_Pooling2D, _Layer); + + function _Pooling2D() { + var _this; + + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, _Pooling2D); + + _this = _possibleConstructorReturn(this, (_Pooling2D.__proto__ || Object.getPrototypeOf(_Pooling2D)).call(this, attrs)); + _this.layerClass = '_Pooling2D'; + var _attrs$pool_size = attrs.pool_size, + pool_size = _attrs$pool_size === void 0 ? [2, 2] : _attrs$pool_size, + _attrs$strides = attrs.strides, + strides = _attrs$strides === void 0 ? null : _attrs$strides, + _attrs$padding = attrs.padding, + padding = _attrs$padding === void 0 ? 'valid' : _attrs$padding, + _attrs$data_format = attrs.data_format, + data_format = _attrs$data_format === void 0 ? 'channels_last' : _attrs$data_format; + + if (Array.isArray(pool_size)) { + _this.poolSize = pool_size; + } else { + _this.poolSize = [pool_size, pool_size]; + } + + if (Array.isArray(strides)) { + _this.strides = strides; + } else if (strides !== null) { + _this.strides = [strides, strides]; + } else { + _this.strides = _this.poolSize; + } + + _this.padding = padding; + _this.dataFormat = data_format; + _this.poolingFunc = 'max'; + + if (_this.gpu) { + _this.poolingProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingProgramSource); + _this.poolingFragmentsProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingFragmentsProgramSource); + } + + return _this; + } + + _createClass(_Pooling2D, [{ + key: "call", + value: function call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + }, { + key: "_calcOutputShape", + value: function _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + var _inputShape = _slicedToArray(inputShape, 3), + inputRows = _inputShape[0], + inputCols = _inputShape[1], + inputChannels = _inputShape[2]; + + var _poolSize = _slicedToArray(this.poolSize, 2), + nbRow = _poolSize[0], + nbCol = _poolSize[1]; + + var outputRows = this.padding === 'same' ? Math.floor((inputRows + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputRows - nbRow + this.strides[0]) / this.strides[0]); + var outputCols = this.padding === 'same' ? Math.floor((inputCols + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputCols - nbCol + this.strides[1]) / this.strides[1]); + var paddingRow = this.padding === 'same' ? Math.max(0, Math.floor((outputRows - 1) * this.strides[0] + nbRow - inputRows)) : 0; + var paddingCol = this.padding === 'same' ? Math.max(0, Math.floor((outputCols - 1) * this.strides[1] + nbCol - inputCols)) : 0; + var paddingRowBefore = Math.floor(paddingRow / 2); + var paddingRowAfter = paddingRow - paddingRowBefore; + var paddingColBefore = Math.floor(paddingCol / 2); + var paddingColAfter = paddingCol - paddingColBefore; + this.outputShape = [outputRows, outputCols, inputChannels]; + this.inputPadding = [paddingRowBefore, paddingRowAfter, paddingColBefore, paddingColAfter]; + } + }, { + key: "_padInput", + value: function _padInput(x) { + if (this.padding === 'same') { + var _x$tensor$shape = _slicedToArray(x.tensor.shape, 3), + inputRows = _x$tensor$shape[0], + inputCols = _x$tensor$shape[1], + inputChannels = _x$tensor$shape[2]; + + var _inputPadding = _slicedToArray(this.inputPadding, 4), + paddingRowBefore = _inputPadding[0], + paddingRowAfter = _inputPadding[1], + paddingColBefore = _inputPadding[2], + paddingColAfter = _inputPadding[3]; + + var newRows = inputRows + paddingRowBefore + paddingRowAfter; + var newCols = inputCols + paddingColBefore + paddingColAfter; + + var _x = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [newRows, newCols, inputChannels]); + + if (this.poolingFunc === 'max') { + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assigns(_x.tensor, Number.NEGATIVE_INFINITY); + } + + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(_x.tensor.hi(inputRows + paddingRowBefore, inputCols + paddingColBefore, inputChannels).lo(paddingRowBefore, paddingColBefore, 0), x.tensor); + return _x; + } + + return x; + } + }, { + key: "_callCPU", + value: function _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this._calcOutputShape(x.tensor.shape); + + x = this._padInput(x); + + var _x$tensor$shape2 = _slicedToArray(x.tensor.shape, 3), + inputRows = _x$tensor$shape2[0], + inputCols = _x$tensor$shape2[1], + inputChannels = _x$tensor$shape2[2]; + + var _poolSize2 = _slicedToArray(this.poolSize, 2), + nbRow = _poolSize2[0], + nbCol = _poolSize2[1]; + + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], this.outputShape); + var patch = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [nbRow, nbCol, inputChannels]); + + var _inputPadding2 = _slicedToArray(this.inputPadding, 4), + paddingRowBefore = _inputPadding2[0], + paddingRowAfter = _inputPadding2[1], + paddingColBefore = _inputPadding2[2], + paddingColAfter = _inputPadding2[3]; + + for (var i = 0, _i = 0; i <= inputRows - nbRow; i += this.strides[0], _i++) { + var nbRowInPadding = 0; + + if (i < paddingRowBefore) { + nbRowInPadding = paddingRowBefore - i; + } else if (i + nbRow > inputRows - paddingRowAfter) { + nbRowInPadding = i + nbRow - (inputRows - paddingRowAfter); + } + + for (var j = 0, _j = 0; j <= inputCols - nbCol; j += this.strides[1], _j++) { + var nbColInPadding = 0; + + if (j < paddingColBefore) { + nbColInPadding = paddingColBefore - j; + } else if (j + nbCol > inputCols - paddingColAfter) { + nbColInPadding = j + nbCol - (inputCols - paddingColAfter); + } + + var nbCellsEffective = (nbRow - nbRowInPadding) * (nbCol - nbColInPadding); + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(patch.tensor, x.tensor.hi(i + nbRow, j + nbCol, inputChannels).lo(i, j, 0)); + + for (var c = 0; c < inputChannels; c++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(_i, _j, c, __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.sup(patch.tensor.pick(null, null, c))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(_i, _j, c, __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.sum(patch.tensor.pick(null, null, c)) / nbCellsEffective); + } + } + } + } + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + }, { + key: "_im2col", + value: function _im2col(x) { + var _x$tensor$shape3 = _slicedToArray(x.tensor.shape, 3), + inputRows = _x$tensor$shape3[0], + inputCols = _x$tensor$shape3[1], + inputChannels = _x$tensor$shape3[2]; + + if (!this.tiledInput) { + this.tiledInput = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputRows * inputCols, inputChannels]); + } + + var patch = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputRows, inputCols]); + var patchRaveled = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputRows * inputCols]); + + for (var c = 0; c < inputChannels; c++) { + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(patch.tensor, x.tensor.pick(null, null, c)); + patchRaveled.replaceTensorData(patch.tensor.data); + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(this.tiledInput.tensor.pick(null, c), patchRaveled.tensor); + } + + return this.tiledInput; + } + }, { + key: "_createIndexMap", + value: function _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + var inputRows = this.inputShape[0]; + var inputCols = this.inputShape[1]; + var rowIndices = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputRows, inputCols]); + var index = 0; + + for (var i = 0; i < inputRows; i++) { + for (var j = 0; j < inputCols; j++) { + rowIndices.tensor.set(i, j, index); + index += 1; + } + } + + if (this.padding === 'same') { + var _inputPadding3 = _slicedToArray(this.inputPadding, 4), + paddingRowBefore = _inputPadding3[0], + paddingRowAfter = _inputPadding3[1], + paddingColBefore = _inputPadding3[2], + paddingColAfter = _inputPadding3[3]; + + inputRows = inputRows + paddingRowBefore + paddingRowAfter; + inputCols = inputCols + paddingColBefore + paddingColAfter; + + var _rowIndices = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputRows, inputCols]); + + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assigns(_rowIndices.tensor, -1); + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(_rowIndices.tensor.hi(this.inputShape[0] + paddingRowBefore, this.inputShape[1] + paddingColBefore).lo(paddingRowBefore, paddingColBefore), rowIndices.tensor); + rowIndices.tensor = _rowIndices.tensor; + } + + var _poolSize3 = _slicedToArray(this.poolSize, 2), + nbRow = _poolSize3[0], + nbCol = _poolSize3[1]; + + var outputRows = this.outputShape[0]; + var outputCols = this.outputShape[1]; + this.poolIndexMap = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [outputRows * outputCols, nbRow * nbCol], { + type: Int32Array + }); + var patchRow = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [nbRow, nbCol]); + var offset = 0; + + for (var _i2 = 0, limit = inputRows - nbRow; _i2 <= limit; _i2 += this.strides[0]) { + for (var _j2 = 0, _limit = inputCols - nbCol; _j2 <= _limit; _j2 += this.strides[1]) { + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(patchRow.tensor, rowIndices.tensor.hi(_i2 + nbRow, _j2 + nbCol).lo(_i2, _j2)); + this.poolIndexMap.tensor.data.set(patchRow.tensor.data, offset); + offset += nbRow * nbCol; + } + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + }, { + key: "_callGPU", + value: function _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + + this._im2col(x); + + this.tiledInput.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(); + + if (!this.output) { + var _outputShape = _slicedToArray(this.outputShape, 3), + outputRows = _outputShape[0], + outputCols = _outputShape[1], + inputChannels = _outputShape[2]; + + var outputTextureShape = [outputRows * outputCols, inputChannels]; + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = __WEBPACK_IMPORTED_MODULE_3__utils_tensorUtils__["b" /* createIndicesFor2DReshaped */](this.outputShape, false, -1); + } + + var input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.tiledInput; + var poolSize = this.poolSize[0] * this.poolSize[1]; + var isMaxPooling = this.poolingFunc === 'max'; + var programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (input.glTextureFragments) { + input.convert2DRowFragmentedGLTextureToColStack(); + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + input.removeGLTextureFragmentsAsColStack(); + } else { + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(2, 0, 1); + } + } + } + }]); + + return _Pooling2D; +}(__WEBPACK_IMPORTED_MODULE_0__Layer__["a" /* default */]); + + + +/***/ }), +/* 175 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _Pooling3D; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Layer__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__utils_tensorUtils__ = __webpack_require__(27); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_ndarray_ops__); +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +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"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _slicedToArray(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"); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } 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 poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(textureSize(poolIndexMap, 0)[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n if (poolIndex != -1) {\r\n float val2 = texelFetch(x, ivec2(out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; +var poolingFragmentsProgramSource = "#version 300 es\r\nprecision highp float;\r\nprecision highp isampler2D;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform isampler2D poolIndexMap;\r\nuniform int channels;\r\nuniform int poolSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 inputSize = textureSize(x, 0);\r\n ivec2 outputSize = textureSize(poolIndexMap, 0);\r\n int out_x = int(float(channels) * outTex.x);\r\n int out_y = int(float(outputSize[1]) * outTex.y);\r\n\r\n float val = 0.;\r\n int count = 0;\r\n for (int i = 0; i < poolSize; ++i) {\r\n int poolIndex = texelFetch(poolIndexMap, ivec2(i, out_y), 0).r;\r\n int fragmentIndex = int(floor(float(poolIndex) / float(inputSize[1])));\r\n if (poolIndex != -1) {\r\n poolIndex = int(mod(float(poolIndex), float(inputSize[1])));\r\n float val2 = texelFetch(x, ivec2(fragmentIndex * channels + out_x, poolIndex), 0).r;\r\n if (isMaxPooling) {\r\n if (count == 0 || val2 > val) {\r\n val = val2;\r\n }\r\n } else {\r\n val += val2;\r\n }\r\n count += 1;\r\n }\r\n }\r\n\r\n if (!isMaxPooling) {\r\n val /= float(count);\r\n }\r\n\r\n outColor = vec4(val);\r\n}\r\n"; + +var _Pooling3D = function (_Layer) { + _inherits(_Pooling3D, _Layer); + + function _Pooling3D() { + var _this; + + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, _Pooling3D); + + _this = _possibleConstructorReturn(this, (_Pooling3D.__proto__ || Object.getPrototypeOf(_Pooling3D)).call(this, attrs)); + _this.layerClass = '_Pooling3D'; + var _attrs$pool_size = attrs.pool_size, + pool_size = _attrs$pool_size === void 0 ? [2, 2, 2] : _attrs$pool_size, + _attrs$strides = attrs.strides, + strides = _attrs$strides === void 0 ? null : _attrs$strides, + _attrs$padding = attrs.padding, + padding = _attrs$padding === void 0 ? 'valid' : _attrs$padding, + _attrs$data_format = attrs.data_format, + data_format = _attrs$data_format === void 0 ? 'channels_last' : _attrs$data_format; + + if (Array.isArray(pool_size)) { + _this.poolSize = pool_size; + } else { + _this.poolSize = [pool_size, pool_size, pool_size]; + } + + if (Array.isArray(strides)) { + _this.strides = strides; + } else if (strides !== null) { + _this.strides = [strides, strides, strides]; + } else { + _this.strides = _this.poolSize; + } + + _this.padding = padding; + _this.dataFormat = data_format; + _this.poolingFunc = 'max'; + + if (_this.gpu) { + _this.poolingProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingProgramSource); + _this.poolingFragmentsProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingFragmentsProgramSource); + } + + return _this; + } + + _createClass(_Pooling3D, [{ + key: "call", + value: function call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + }, { + key: "_calcOutputShape", + value: function _calcOutputShape(inputShape) { + if (this.outputShape && this.inputPadding) { + return; + } + + var _inputShape = _slicedToArray(inputShape, 4), + inputDim1 = _inputShape[0], + inputDim2 = _inputShape[1], + inputDim3 = _inputShape[2], + inputChannels = _inputShape[3]; + + var _poolSize = _slicedToArray(this.poolSize, 3), + poolDim1 = _poolSize[0], + poolDim2 = _poolSize[1], + poolDim3 = _poolSize[2]; + + var outputDim1 = this.padding === 'same' ? Math.floor((inputDim1 + this.strides[0] - 1) / this.strides[0]) : Math.floor((inputDim1 - poolDim1 + this.strides[0]) / this.strides[0]); + var outputDim2 = this.padding === 'same' ? Math.floor((inputDim2 + this.strides[1] - 1) / this.strides[1]) : Math.floor((inputDim2 - poolDim2 + this.strides[1]) / this.strides[1]); + var outputDim3 = this.padding === 'same' ? Math.floor((inputDim3 + this.strides[2] - 1) / this.strides[2]) : Math.floor((inputDim3 - poolDim3 + this.strides[2]) / this.strides[2]); + var paddingDim1 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim1 - 1) * this.strides[0] + poolDim1 - inputDim1)) : 0; + var paddingDim2 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim2 - 1) * this.strides[1] + poolDim2 - inputDim2)) : 0; + var paddingDim3 = this.padding === 'same' ? Math.max(0, Math.floor((outputDim3 - 1) * this.strides[2] + poolDim3 - inputDim3)) : 0; + var paddingDim1Before = Math.floor(paddingDim1 / 2); + var paddingDim1After = paddingDim1 - paddingDim1Before; + var paddingDim2Before = Math.floor(paddingDim2 / 2); + var paddingDim2After = paddingDim2 - paddingDim2Before; + var paddingDim3Before = Math.floor(paddingDim3 / 2); + var paddingDim3After = paddingDim3 - paddingDim3Before; + this.outputShape = [outputDim1, outputDim2, outputDim3, inputChannels]; + this.inputPadding = [paddingDim1Before, paddingDim1After, paddingDim2Before, paddingDim2After, paddingDim3Before, paddingDim3After]; + } + }, { + key: "_padInput", + value: function _padInput(x) { + if (this.padding === 'same') { + var _x$tensor$shape = _slicedToArray(x.tensor.shape, 4), + inputDim1 = _x$tensor$shape[0], + inputDim2 = _x$tensor$shape[1], + inputDim3 = _x$tensor$shape[2], + inputChannels = _x$tensor$shape[3]; + + var _inputPadding = _slicedToArray(this.inputPadding, 6), + paddingDim1Before = _inputPadding[0], + paddingDim1After = _inputPadding[1], + paddingDim2Before = _inputPadding[2], + paddingDim2After = _inputPadding[3], + paddingDim3Before = _inputPadding[4], + paddingDim3After = _inputPadding[5]; + + var newDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + var newDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + var newDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + + var _x = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [newDim1, newDim2, newDim3, inputChannels]); + + if (this.poolingFunc === 'max') { + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assigns(_x.tensor, Number.NEGATIVE_INFINITY); + } + + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(_x.tensor.hi(inputDim1 + paddingDim1Before, inputDim2 + paddingDim2Before, inputDim3 + paddingDim3Before, inputChannels).lo(paddingDim1Before, paddingDim2Before, paddingDim3Before, 0), x.tensor); + return _x; + } + + return x; + } + }, { + key: "_callCPU", + value: function _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this._calcOutputShape(x.tensor.shape); + + x = this._padInput(x); + + var _x$tensor$shape2 = _slicedToArray(x.tensor.shape, 4), + inputDim1 = _x$tensor$shape2[0], + inputDim2 = _x$tensor$shape2[1], + inputDim3 = _x$tensor$shape2[2], + inputChannels = _x$tensor$shape2[3]; + + var _poolSize2 = _slicedToArray(this.poolSize, 3), + poolDim1 = _poolSize2[0], + poolDim2 = _poolSize2[1], + poolDim3 = _poolSize2[2]; + + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], this.outputShape); + var patch = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [poolDim1, poolDim2, poolDim3, inputChannels]); + + var _inputPadding2 = _slicedToArray(this.inputPadding, 6), + paddingDim1Before = _inputPadding2[0], + paddingDim1After = _inputPadding2[1], + paddingDim2Before = _inputPadding2[2], + paddingDim2After = _inputPadding2[3], + paddingDim3Before = _inputPadding2[4], + paddingDim3After = _inputPadding2[5]; + + for (var i = 0, _i = 0; i <= inputDim1 - poolDim1; i += this.strides[0], _i++) { + var dim1InPadding = 0; + + if (i < paddingDim1Before) { + dim1InPadding = paddingDim1Before - i; + } else if (i + poolDim1 > inputDim1 - paddingDim1After) { + dim1InPadding = i + poolDim1 - (inputDim1 - paddingDim1After); + } + + for (var j = 0, _j = 0; j <= inputDim2 - poolDim2; j += this.strides[1], _j++) { + var dim2InPadding = 0; + + if (j < paddingDim2Before) { + dim2InPadding = paddingDim2Before - j; + } else if (j + poolDim2 > inputDim2 - paddingDim2After) { + dim2InPadding = j + poolDim2 - (inputDim2 - paddingDim2After); + } + + for (var k = 0, _k = 0; k <= inputDim3 - poolDim3; k += this.strides[2], _k++) { + var dim3InPadding = 0; + + if (k < paddingDim3Before) { + dim3InPadding = paddingDim3Before - k; + } else if (k + poolDim3 > inputDim3 - paddingDim3After) { + dim3InPadding = k + poolDim3 - (inputDim3 - paddingDim3After); + } + + var nbCellsEffective = (poolDim1 - dim1InPadding) * (poolDim2 - dim2InPadding) * (poolDim3 - dim3InPadding); + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(patch.tensor, x.tensor.hi(i + poolDim1, j + poolDim2, k + poolDim3, inputChannels).lo(i, j, k, 0)); + + for (var c = 0; c < inputChannels; c++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(_i, _j, _k, c, __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.sup(patch.tensor.pick(null, null, null, c))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(_i, _j, _k, c, __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.sum(patch.tensor.pick(null, null, null, c)) / nbCellsEffective); + } + } + } + } + } + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + }, { + key: "_vol2col", + value: function _vol2col(x) { + var _x$tensor$shape3 = _slicedToArray(x.tensor.shape, 4), + inputDim1 = _x$tensor$shape3[0], + inputDim2 = _x$tensor$shape3[1], + inputDim3 = _x$tensor$shape3[2], + inputChannels = _x$tensor$shape3[3]; + + if (!this.tiledInput) { + this.tiledInput = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputDim1 * inputDim2 * inputDim3, inputChannels]); + } + + var patch = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputDim1, inputDim2, inputDim3]); + var patchRaveled = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputDim1 * inputDim2 * inputDim3]); + + for (var c = 0; c < inputChannels; c++) { + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(patch.tensor, x.tensor.pick(null, null, null, c)); + patchRaveled.replaceTensorData(patch.tensor.data); + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(this.tiledInput.tensor.pick(null, c), patchRaveled.tensor); + } + + return this.tiledInput; + } + }, { + key: "_createIndexMap", + value: function _createIndexMap() { + if (this.poolIndexMap) { + return; + } + + var inputDim1 = this.inputShape[0]; + var inputDim2 = this.inputShape[1]; + var inputDim3 = this.inputShape[2]; + var rowIndices = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputDim1, inputDim2, inputDim3]); + var index = 0; + + for (var i = 0; i < inputDim1; i++) { + for (var j = 0; j < inputDim2; j++) { + for (var k = 0; k < inputDim3; k++) { + rowIndices.tensor.set(i, j, k, index); + index += 1; + } + } + } + + if (this.padding === 'same') { + var _inputPadding3 = _slicedToArray(this.inputPadding, 6), + paddingDim1Before = _inputPadding3[0], + paddingDim1After = _inputPadding3[1], + paddingDim2Before = _inputPadding3[2], + paddingDim2After = _inputPadding3[3], + paddingDim3Before = _inputPadding3[4], + paddingDim3After = _inputPadding3[5]; + + inputDim1 = inputDim1 + paddingDim1Before + paddingDim1After; + inputDim2 = inputDim2 + paddingDim2Before + paddingDim2After; + inputDim3 = inputDim3 + paddingDim3Before + paddingDim3After; + + var _rowIndices = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [inputDim1, inputDim2, inputDim3]); + + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assigns(_rowIndices.tensor, -1); + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(_rowIndices.tensor.hi(this.inputShape[0] + paddingDim1Before, this.inputShape[1] + paddingDim2Before, this.inputShape[2] + paddingDim3Before).lo(paddingDim1Before, paddingDim2Before, paddingDim3Before), rowIndices.tensor); + rowIndices.tensor = _rowIndices.tensor; + } + + var _poolSize3 = _slicedToArray(this.poolSize, 3), + poolDim1 = _poolSize3[0], + poolDim2 = _poolSize3[1], + poolDim3 = _poolSize3[2]; + + var outputDim1 = this.outputShape[0]; + var outputDim2 = this.outputShape[1]; + var outputDim3 = this.outputShape[2]; + this.poolIndexMap = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [outputDim1 * outputDim2 * outputDim3, poolDim1 * poolDim2 * poolDim3], { + type: Int32Array + }); + var patchRow = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [poolDim1, poolDim2, poolDim3]); + var offset = 0; + + for (var _i2 = 0, limit = inputDim1 - poolDim1; _i2 <= limit; _i2 += this.strides[0]) { + for (var _j2 = 0, _limit = inputDim2 - poolDim2; _j2 <= _limit; _j2 += this.strides[1]) { + for (var _k2 = 0, _limit2 = inputDim3 - poolDim3; _k2 <= _limit2; _k2 += this.strides[2]) { + __WEBPACK_IMPORTED_MODULE_4_ndarray_ops___default.a.assign(patchRow.tensor, rowIndices.tensor.hi(_i2 + poolDim1, _j2 + poolDim2, _k2 + poolDim3).lo(_i2, _j2, _k2)); + this.poolIndexMap.tensor.data.set(patchRow.tensor.data, offset); + offset += poolDim1 * poolDim2 * poolDim3; + } + } + } + + this.poolIndexMap.createGLTexture({ + type: '2d', + format: 'int', + supportsTextureFragments: true + }); + } + }, { + key: "_callGPU", + value: function _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + + this._vol2col(x); + + this.tiledInput.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + } + + this._calcOutputShape(this.inputShape); + + this._createIndexMap(); + + if (!this.output) { + var _outputShape = _slicedToArray(this.outputShape, 4), + outputDim1 = _outputShape[0], + outputDim2 = _outputShape[1], + outputDim3 = _outputShape[2], + inputChannels = _outputShape[3]; + + var outputTextureShape = [outputDim1 * outputDim2 * outputDim3, inputChannels]; + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], outputTextureShape); + this.output.createGLTexture({ + type: '2d', + format: 'float', + supportsTextureFragments: true + }); + this.output.is2DReshaped = true; + this.output.originalShape = this.outputShape; + this.output.indicesForReshaped = __WEBPACK_IMPORTED_MODULE_3__utils_tensorUtils__["b" /* createIndicesFor2DReshaped */](this.outputShape, false, -1); + } + + var input = x.is2DReshaped || x.is2DSquareReshaped ? x : this.tiledInput; + var poolSize = this.poolSize[0] * this.poolSize[1] * this.poolSize[2]; + var isMaxPooling = this.poolingFunc === 'max'; + var programUniforms = [{ + value: this.output.glTextureShape[1], + type: 'int', + name: 'channels' + }, { + value: poolSize, + type: 'int', + name: 'poolSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }]; + + if (input.glTextureFragments) { + input.convert2DRowFragmentedGLTextureToColStack(); + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingFragmentsProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms, + supportsTextureFragments: true + }); + input.removeGLTextureFragmentsAsColStack(); + } else { + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: input, + name: 'x' + }, { + input: this.poolIndexMap, + name: 'poolIndexMap' + }], + uniforms: programUniforms + }); + } + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + this.output.reshapeFrom2D(); + + if (this.dataFormat === 'channels_first') { + this.output.tensor = this.output.tensor.transpose(3, 0, 1, 2); + } + } + } + }]); + + return _Pooling3D; +}(__WEBPACK_IMPORTED_MODULE_0__Layer__["a" /* default */]); + + + +/***/ }), +/* 176 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _GlobalPooling1D; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Layer__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_ndarray_ops__); +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +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"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _slicedToArray(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"); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } 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 poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +var _GlobalPooling1D = function (_Layer) { + _inherits(_GlobalPooling1D, _Layer); + + function _GlobalPooling1D() { + var _this; + + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, _GlobalPooling1D); + + _this = _possibleConstructorReturn(this, (_GlobalPooling1D.__proto__ || Object.getPrototypeOf(_GlobalPooling1D)).call(this, attrs)); + _this.layerClass = '_GlobalPooling1D'; + var _attrs$data_format = attrs.data_format, + data_format = _attrs$data_format === void 0 ? 'channels_last' : _attrs$data_format; + _this.dataFormat = data_format; + _this.poolingFunc = 'max'; + + if (_this.gpu) { + _this.poolingProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingProgramSource); + } + + return _this; + } + + _createClass(_GlobalPooling1D, [{ + key: "call", + value: function call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + }, { + key: "_callCPU", + value: function _callCPU(x) { + var _x$tensor$shape = _slicedToArray(x.tensor.shape, 2), + steps = _x$tensor$shape[0], + features = _x$tensor$shape[1]; + + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [features]); + + for (var i = 0, len = features; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.sup(x.tensor.pick(null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.sum(x.tensor.pick(null, i)) / steps); + } + } + } + }, { + key: "_callGPU", + value: function _callGPU(x) { + if (!x.glTexture) { + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + this.inputShape = x.tensor.shape; + + if (!this.output) { + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [this.inputShape[1]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + var isMaxPooling = this.poolingFunc === 'max'; + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + }]); + + return _GlobalPooling1D; +}(__WEBPACK_IMPORTED_MODULE_0__Layer__["a" /* default */]); + + + +/***/ }), +/* 177 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _GlobalPooling2D; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Layer__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_ndarray_ops__); +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +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"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _slicedToArray(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"); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } 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 poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +var _GlobalPooling2D = function (_Layer) { + _inherits(_GlobalPooling2D, _Layer); + + function _GlobalPooling2D() { + var _this; + + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, _GlobalPooling2D); + + _this = _possibleConstructorReturn(this, (_GlobalPooling2D.__proto__ || Object.getPrototypeOf(_GlobalPooling2D)).call(this, attrs)); + _this.layerClass = '_GlobalPooling2D'; + var _attrs$data_format = attrs.data_format, + data_format = _attrs$data_format === void 0 ? 'channels_last' : _attrs$data_format; + _this.dataFormat = data_format; + _this.poolingFunc = 'max'; + + if (_this.gpu) { + _this.poolingProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingProgramSource); + } + + return _this; + } + + _createClass(_GlobalPooling2D, [{ + key: "call", + value: function call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + }, { + key: "_callCPU", + value: function _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + var _x$tensor$shape = _slicedToArray(x.tensor.shape, 3), + rows = _x$tensor$shape[0], + cols = _x$tensor$shape[1], + channels = _x$tensor$shape[2]; + + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [channels]); + + for (var i = 0, len = channels; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.sup(x.tensor.pick(null, null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.sum(x.tensor.pick(null, null, i)) / (rows * cols)); + } + } + } + }, { + key: "_callGPU", + value: function _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 0); + } + + this.inputShape = x.tensor.shape; + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [this.inputShape[2]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + var isMaxPooling = this.poolingFunc === 'max'; + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0] * this.inputShape[1], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + }]); + + return _GlobalPooling2D; +}(__WEBPACK_IMPORTED_MODULE_0__Layer__["a" /* default */]); + + + +/***/ }), +/* 178 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _GlobalPooling3D; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Layer__ = __webpack_require__(3); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_ndarray_ops__); +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +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"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _slicedToArray(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"); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } 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 poolingProgramSource = "#version 300 es\r\nprecision highp float;\r\n\r\nin vec2 outTex;\r\nuniform sampler2D x;\r\nuniform int channelDataSize;\r\nuniform bool isMaxPooling;\r\nout vec4 outColor;\r\n\r\nvoid main() {\r\n ivec2 size = textureSize(x, 0);\r\n int out_x = int(float(size[0]) * outTex.x);\r\n int out_y = int(float(size[1]) * outTex.y);\r\n\r\n if (isMaxPooling) {\r\n // GlobalMaxPooling\r\n float maxval = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n if (j == 0 || val > maxval) {\r\n maxval = val;\r\n }\r\n }\r\n outColor = vec4(maxval);\r\n } else {\r\n // GlobalAveragePooling\r\n float sum = 0.0;\r\n for (int j = 0; j < size[1]; ++j) {\r\n float val = texelFetch(x, ivec2(out_x, j), 0).r;\r\n sum += val;\r\n }\r\n outColor = vec4(sum / float(channelDataSize));\r\n }\r\n}\r\n"; + +var _GlobalPooling3D = function (_Layer) { + _inherits(_GlobalPooling3D, _Layer); + + function _GlobalPooling3D() { + var _this; + + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, _GlobalPooling3D); + + _this = _possibleConstructorReturn(this, (_GlobalPooling3D.__proto__ || Object.getPrototypeOf(_GlobalPooling3D)).call(this, attrs)); + _this.layerClass = '_GlobalPooling3D'; + var _attrs$data_format = attrs.data_format, + data_format = _attrs$data_format === void 0 ? 'channels_last' : _attrs$data_format; + _this.dataFormat = data_format; + _this.poolingFunc = 'max'; + + if (_this.gpu) { + _this.poolingProgram = __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].compileProgram(poolingProgramSource); + } + + return _this; + } + + _createClass(_GlobalPooling3D, [{ + key: "call", + value: function call(x) { + if (this.gpu) { + this._callGPU(x); + } else { + this._callCPU(x); + } + + return this.output; + } + }, { + key: "_callCPU", + value: function _callCPU(x) { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + var _x$tensor$shape = _slicedToArray(x.tensor.shape, 4), + dim1 = _x$tensor$shape[0], + dim2 = _x$tensor$shape[1], + dim3 = _x$tensor$shape[2], + channels = _x$tensor$shape[3]; + + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [channels]); + + for (var i = 0, len = channels; i < len; i++) { + if (this.poolingFunc === 'max') { + this.output.tensor.set(i, __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.sup(x.tensor.pick(null, null, null, i))); + } else if (this.poolingFunc === 'average') { + this.output.tensor.set(i, __WEBPACK_IMPORTED_MODULE_3_ndarray_ops___default.a.sum(x.tensor.pick(null, null, null, i)) / (dim1 * dim2 * dim3)); + } + } + } + }, { + key: "_callGPU", + value: function _callGPU(x) { + if (x.is2DReshaped || x.is2DSquareReshaped) { + this.inputShape = x.originalShape; + } else { + if (this.dataFormat === 'channels_first') { + x.tensor = x.tensor.transpose(1, 2, 3, 0); + } + + this.inputShape = x.tensor.shape; + x.reshapeTo2D(); + x.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + if (!this.output) { + this.output = new __WEBPACK_IMPORTED_MODULE_1__Tensor__["a" /* default */]([], [this.inputShape[3]]); + this.output.createGLTexture({ + type: '2d', + format: 'float' + }); + } + + var isMaxPooling = this.poolingFunc === 'max'; + __WEBPACK_IMPORTED_MODULE_2__WebGL2__["b" /* webgl2 */].runProgram({ + program: this.poolingProgram, + output: this.output, + inputs: [{ + input: x, + name: 'x' + }], + uniforms: [{ + value: this.inputShape[0] * this.inputShape[1] * this.inputShape[2], + type: 'int', + name: 'channelDataSize' + }, { + value: +isMaxPooling, + type: 'bool', + name: 'isMaxPooling' + }] + }); + + if (this.outbound.length === 0) { + this.output.transferFromGLTexture(); + } + } + }]); + + return _GlobalPooling3D; +}(__WEBPACK_IMPORTED_MODULE_0__Layer__["a" /* default */]); + + + +/***/ }), +/* 179 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__SimpleRNN__ = __webpack_require__(535); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__LSTM__ = __webpack_require__(536); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__GRU__ = __webpack_require__(537); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "SimpleRNN", function() { return __WEBPACK_IMPORTED_MODULE_0__SimpleRNN__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "LSTM", function() { return __WEBPACK_IMPORTED_MODULE_1__LSTM__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "GRU", function() { return __WEBPACK_IMPORTED_MODULE_2__GRU__["a"]; }); + + + + + +/***/ }), +/* 180 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = Writer; + +var util = __webpack_require__(40); + +var BufferWriter; // cyclic + +var LongBits = util.LongBits, + base64 = util.base64, + utf8 = util.utf8; + +/** + * Constructs a new writer operation instance. + * @classdesc Scheduled writer operation. + * @constructor + * @param {function(*, Uint8Array, number)} fn Function to call + * @param {number} len Value byte length + * @param {*} val Value to write + * @ignore + */ +function Op(fn, len, val) { + + /** + * Function to call. + * @type {function(Uint8Array, number, *)} + */ + this.fn = fn; + + /** + * Value byte length. + * @type {number} + */ + this.len = len; + + /** + * Next operation. + * @type {Writer.Op|undefined} + */ + this.next = undefined; + + /** + * Value to write. + * @type {*} + */ + this.val = val; // type varies +} + +/* istanbul ignore next */ +function noop() {} // eslint-disable-line no-empty-function + +/** + * Constructs a new writer state instance. + * @classdesc Copied writer state. + * @memberof Writer + * @constructor + * @param {Writer} writer Writer to copy state from + * @ignore + */ +function State(writer) { + + /** + * Current head. + * @type {Writer.Op} + */ + this.head = writer.head; + + /** + * Current tail. + * @type {Writer.Op} + */ + this.tail = writer.tail; + + /** + * Current buffer length. + * @type {number} + */ + this.len = writer.len; + + /** + * Next state. + * @type {State|null} + */ + this.next = writer.states; +} + +/** + * Constructs a new writer instance. + * @classdesc Wire format writer using `Uint8Array` if available, otherwise `Array`. + * @constructor + */ +function Writer() { + + /** + * Current length. + * @type {number} + */ + this.len = 0; + + /** + * Operations head. + * @type {Object} + */ + this.head = new Op(noop, 0, 0); + + /** + * Operations tail + * @type {Object} + */ + this.tail = this.head; + + /** + * Linked forked states. + * @type {Object|null} + */ + this.states = null; + + // When a value is written, the writer calculates its byte length and puts it into a linked + // list of operations to perform when finish() is called. This both allows us to allocate + // buffers of the exact required size and reduces the amount of work we have to do compared + // to first calculating over objects and then encoding over objects. In our case, the encoding + // part is just a linked list walk calling operations with already prepared values. +} + +/** + * Creates a new writer. + * @function + * @returns {BufferWriter|Writer} A {@link BufferWriter} when Buffers are supported, otherwise a {@link Writer} + */ +Writer.create = util.Buffer + ? function create_buffer_setup() { + return (Writer.create = function create_buffer() { + return new BufferWriter(); + })(); + } + /* istanbul ignore next */ + : function create_array() { + return new Writer(); + }; + +/** + * Allocates a buffer of the specified size. + * @param {number} size Buffer size + * @returns {Uint8Array} Buffer + */ +Writer.alloc = function alloc(size) { + return new util.Array(size); +}; + +// Use Uint8Array buffer pool in the browser, just like node does with buffers +/* istanbul ignore else */ +if (util.Array !== Array) + Writer.alloc = util.pool(Writer.alloc, util.Array.prototype.subarray); + +/** + * Pushes a new operation to the queue. + * @param {function(Uint8Array, number, *)} fn Function to call + * @param {number} len Value byte length + * @param {number} val Value to write + * @returns {Writer} `this` + * @private + */ +Writer.prototype._push = function push(fn, len, val) { + this.tail = this.tail.next = new Op(fn, len, val); + this.len += len; + return this; +}; + +function writeByte(val, buf, pos) { + buf[pos] = val & 255; +} + +function writeVarint32(val, buf, pos) { + while (val > 127) { + buf[pos++] = val & 127 | 128; + val >>>= 7; + } + buf[pos] = val; +} + +/** + * Constructs a new varint writer operation instance. + * @classdesc Scheduled varint writer operation. + * @extends Op + * @constructor + * @param {number} len Value byte length + * @param {number} val Value to write + * @ignore + */ +function VarintOp(len, val) { + this.len = len; + this.next = undefined; + this.val = val; +} + +VarintOp.prototype = Object.create(Op.prototype); +VarintOp.prototype.fn = writeVarint32; + +/** + * Writes an unsigned 32 bit value as a varint. + * @param {number} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.uint32 = function write_uint32(value) { + // here, the call to this.push has been inlined and a varint specific Op subclass is used. + // uint32 is by far the most frequently used operation and benefits significantly from this. + this.len += (this.tail = this.tail.next = new VarintOp( + (value = value >>> 0) + < 128 ? 1 + : value < 16384 ? 2 + : value < 2097152 ? 3 + : value < 268435456 ? 4 + : 5, + value)).len; + return this; +}; + +/** + * Writes a signed 32 bit value as a varint. + * @function + * @param {number} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.int32 = function write_int32(value) { + return value < 0 + ? this._push(writeVarint64, 10, LongBits.fromNumber(value)) // 10 bytes per spec + : this.uint32(value); +}; + +/** + * Writes a 32 bit value as a varint, zig-zag encoded. + * @param {number} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.sint32 = function write_sint32(value) { + return this.uint32((value << 1 ^ value >> 31) >>> 0); +}; + +function writeVarint64(val, buf, pos) { + while (val.hi) { + buf[pos++] = val.lo & 127 | 128; + val.lo = (val.lo >>> 7 | val.hi << 25) >>> 0; + val.hi >>>= 7; + } + while (val.lo > 127) { + buf[pos++] = val.lo & 127 | 128; + val.lo = val.lo >>> 7; + } + buf[pos++] = val.lo; +} + +/** + * Writes an unsigned 64 bit value as a varint. + * @param {Long|number|string} value Value to write + * @returns {Writer} `this` + * @throws {TypeError} If `value` is a string and no long library is present. + */ +Writer.prototype.uint64 = function write_uint64(value) { + var bits = LongBits.from(value); + return this._push(writeVarint64, bits.length(), bits); +}; + +/** + * Writes a signed 64 bit value as a varint. + * @function + * @param {Long|number|string} value Value to write + * @returns {Writer} `this` + * @throws {TypeError} If `value` is a string and no long library is present. + */ +Writer.prototype.int64 = Writer.prototype.uint64; + +/** + * Writes a signed 64 bit value as a varint, zig-zag encoded. + * @param {Long|number|string} value Value to write + * @returns {Writer} `this` + * @throws {TypeError} If `value` is a string and no long library is present. + */ +Writer.prototype.sint64 = function write_sint64(value) { + var bits = LongBits.from(value).zzEncode(); + return this._push(writeVarint64, bits.length(), bits); +}; + +/** + * Writes a boolish value as a varint. + * @param {boolean} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.bool = function write_bool(value) { + return this._push(writeByte, 1, value ? 1 : 0); +}; + +function writeFixed32(val, buf, pos) { + buf[pos ] = val & 255; + buf[pos + 1] = val >>> 8 & 255; + buf[pos + 2] = val >>> 16 & 255; + buf[pos + 3] = val >>> 24; +} + +/** + * Writes an unsigned 32 bit value as fixed 32 bits. + * @param {number} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.fixed32 = function write_fixed32(value) { + return this._push(writeFixed32, 4, value >>> 0); +}; + +/** + * Writes a signed 32 bit value as fixed 32 bits. + * @function + * @param {number} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.sfixed32 = Writer.prototype.fixed32; + +/** + * Writes an unsigned 64 bit value as fixed 64 bits. + * @param {Long|number|string} value Value to write + * @returns {Writer} `this` + * @throws {TypeError} If `value` is a string and no long library is present. + */ +Writer.prototype.fixed64 = function write_fixed64(value) { + var bits = LongBits.from(value); + return this._push(writeFixed32, 4, bits.lo)._push(writeFixed32, 4, bits.hi); +}; + +/** + * Writes a signed 64 bit value as fixed 64 bits. + * @function + * @param {Long|number|string} value Value to write + * @returns {Writer} `this` + * @throws {TypeError} If `value` is a string and no long library is present. + */ +Writer.prototype.sfixed64 = Writer.prototype.fixed64; + +/** + * Writes a float (32 bit). + * @function + * @param {number} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.float = function write_float(value) { + return this._push(util.float.writeFloatLE, 4, value); +}; + +/** + * Writes a double (64 bit float). + * @function + * @param {number} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.double = function write_double(value) { + return this._push(util.float.writeDoubleLE, 8, value); +}; + +var writeBytes = util.Array.prototype.set + ? function writeBytes_set(val, buf, pos) { + buf.set(val, pos); // also works for plain array values + } + /* istanbul ignore next */ + : function writeBytes_for(val, buf, pos) { + for (var i = 0; i < val.length; ++i) + buf[pos + i] = val[i]; + }; + +/** + * Writes a sequence of bytes. + * @param {Uint8Array|string} value Buffer or base64 encoded string to write + * @returns {Writer} `this` + */ +Writer.prototype.bytes = function write_bytes(value) { + var len = value.length >>> 0; + if (!len) + return this._push(writeByte, 1, 0); + if (util.isString(value)) { + var buf = Writer.alloc(len = base64.length(value)); + base64.decode(value, buf, 0); + value = buf; + } + return this.uint32(len)._push(writeBytes, len, value); +}; + +/** + * Writes a string. + * @param {string} value Value to write + * @returns {Writer} `this` + */ +Writer.prototype.string = function write_string(value) { + var len = utf8.length(value); + return len + ? this.uint32(len)._push(utf8.write, len, value) + : this._push(writeByte, 1, 0); +}; + +/** + * Forks this writer's state by pushing it to a stack. + * Calling {@link Writer#reset|reset} or {@link Writer#ldelim|ldelim} resets the writer to the previous state. + * @returns {Writer} `this` + */ +Writer.prototype.fork = function fork() { + this.states = new State(this); + this.head = this.tail = new Op(noop, 0, 0); + this.len = 0; + return this; +}; + +/** + * Resets this instance to the last state. + * @returns {Writer} `this` + */ +Writer.prototype.reset = function reset() { + if (this.states) { + this.head = this.states.head; + this.tail = this.states.tail; + this.len = this.states.len; + this.states = this.states.next; + } else { + this.head = this.tail = new Op(noop, 0, 0); + this.len = 0; + } + return this; +}; + +/** + * Resets to the last state and appends the fork state's current write length as a varint followed by its operations. + * @returns {Writer} `this` + */ +Writer.prototype.ldelim = function ldelim() { + var head = this.head, + tail = this.tail, + len = this.len; + this.reset().uint32(len); + if (len) { + this.tail.next = head.next; // skip noop + this.tail = tail; + this.len += len; + } + return this; +}; + +/** + * Finishes the write operation. + * @returns {Uint8Array} Finished buffer + */ +Writer.prototype.finish = function finish() { + var head = this.head.next, // skip noop + buf = this.constructor.alloc(this.len), + pos = 0; + while (head) { + head.fn(head.val, buf, pos); + pos += head.len; + head = head.next; + } + // this.head = this.tail = null; + return buf; +}; + +Writer._configure = function(BufferWriter_) { + BufferWriter = BufferWriter_; +}; + + +/***/ }), +/* 181 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +module.exports = Reader; + +var util = __webpack_require__(40); + +var BufferReader; // cyclic + +var LongBits = util.LongBits, + utf8 = util.utf8; + +/* istanbul ignore next */ +function indexOutOfRange(reader, writeLength) { + return RangeError("index out of range: " + reader.pos + " + " + (writeLength || 1) + " > " + reader.len); +} + +/** + * Constructs a new reader instance using the specified buffer. + * @classdesc Wire format reader using `Uint8Array` if available, otherwise `Array`. + * @constructor + * @param {Uint8Array} buffer Buffer to read from + */ +function Reader(buffer) { + + /** + * Read buffer. + * @type {Uint8Array} + */ + this.buf = buffer; + + /** + * Read buffer position. + * @type {number} + */ + this.pos = 0; + + /** + * Read buffer length. + * @type {number} + */ + this.len = buffer.length; +} + +var create_array = typeof Uint8Array !== "undefined" + ? function create_typed_array(buffer) { + if (buffer instanceof Uint8Array || Array.isArray(buffer)) + return new Reader(buffer); + throw Error("illegal buffer"); + } + /* istanbul ignore next */ + : function create_array(buffer) { + if (Array.isArray(buffer)) + return new Reader(buffer); + throw Error("illegal buffer"); + }; + +/** + * Creates a new reader using the specified buffer. + * @function + * @param {Uint8Array|Buffer} buffer Buffer to read from + * @returns {Reader|BufferReader} A {@link BufferReader} if `buffer` is a Buffer, otherwise a {@link Reader} + * @throws {Error} If `buffer` is not a valid buffer + */ +Reader.create = util.Buffer + ? function create_buffer_setup(buffer) { + return (Reader.create = function create_buffer(buffer) { + return util.Buffer.isBuffer(buffer) + ? new BufferReader(buffer) + /* istanbul ignore next */ + : create_array(buffer); + })(buffer); + } + /* istanbul ignore next */ + : create_array; + +Reader.prototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */ util.Array.prototype.slice; + +/** + * Reads a varint as an unsigned 32 bit value. + * @function + * @returns {number} Value read + */ +Reader.prototype.uint32 = (function read_uint32_setup() { + var value = 4294967295; // optimizer type-hint, tends to deopt otherwise (?!) + return function read_uint32() { + value = ( this.buf[this.pos] & 127 ) >>> 0; if (this.buf[this.pos++] < 128) return value; + value = (value | (this.buf[this.pos] & 127) << 7) >>> 0; if (this.buf[this.pos++] < 128) return value; + value = (value | (this.buf[this.pos] & 127) << 14) >>> 0; if (this.buf[this.pos++] < 128) return value; + value = (value | (this.buf[this.pos] & 127) << 21) >>> 0; if (this.buf[this.pos++] < 128) return value; + value = (value | (this.buf[this.pos] & 15) << 28) >>> 0; if (this.buf[this.pos++] < 128) return value; + + /* istanbul ignore if */ + if ((this.pos += 5) > this.len) { + this.pos = this.len; + throw indexOutOfRange(this, 10); + } + return value; + }; +})(); + +/** + * Reads a varint as a signed 32 bit value. + * @returns {number} Value read + */ +Reader.prototype.int32 = function read_int32() { + return this.uint32() | 0; +}; + +/** + * Reads a zig-zag encoded varint as a signed 32 bit value. + * @returns {number} Value read + */ +Reader.prototype.sint32 = function read_sint32() { + var value = this.uint32(); + return value >>> 1 ^ -(value & 1) | 0; +}; + +/* eslint-disable no-invalid-this */ + +function readLongVarint() { + // tends to deopt with local vars for octet etc. + var bits = new LongBits(0, 0); + var i = 0; + if (this.len - this.pos > 4) { // fast route (lo) + for (; i < 4; ++i) { + // 1st..4th + bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0; + if (this.buf[this.pos++] < 128) + return bits; + } + // 5th + bits.lo = (bits.lo | (this.buf[this.pos] & 127) << 28) >>> 0; + bits.hi = (bits.hi | (this.buf[this.pos] & 127) >> 4) >>> 0; + if (this.buf[this.pos++] < 128) + return bits; + i = 0; + } else { + for (; i < 3; ++i) { + /* istanbul ignore if */ + if (this.pos >= this.len) + throw indexOutOfRange(this); + // 1st..3th + bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0; + if (this.buf[this.pos++] < 128) + return bits; + } + // 4th + bits.lo = (bits.lo | (this.buf[this.pos++] & 127) << i * 7) >>> 0; + return bits; + } + if (this.len - this.pos > 4) { // fast route (hi) + for (; i < 5; ++i) { + // 6th..10th + bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0; + if (this.buf[this.pos++] < 128) + return bits; + } + } else { + for (; i < 5; ++i) { + /* istanbul ignore if */ + if (this.pos >= this.len) + throw indexOutOfRange(this); + // 6th..10th + bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0; + if (this.buf[this.pos++] < 128) + return bits; + } + } + /* istanbul ignore next */ + throw Error("invalid varint encoding"); +} + +/* eslint-enable no-invalid-this */ + +/** + * Reads a varint as a signed 64 bit value. + * @name Reader#int64 + * @function + * @returns {Long} Value read + */ + +/** + * Reads a varint as an unsigned 64 bit value. + * @name Reader#uint64 + * @function + * @returns {Long} Value read + */ + +/** + * Reads a zig-zag encoded varint as a signed 64 bit value. + * @name Reader#sint64 + * @function + * @returns {Long} Value read + */ + +/** + * Reads a varint as a boolean. + * @returns {boolean} Value read + */ +Reader.prototype.bool = function read_bool() { + return this.uint32() !== 0; +}; + +function readFixed32_end(buf, end) { // note that this uses `end`, not `pos` + return (buf[end - 4] + | buf[end - 3] << 8 + | buf[end - 2] << 16 + | buf[end - 1] << 24) >>> 0; +} + +/** + * Reads fixed 32 bits as an unsigned 32 bit integer. + * @returns {number} Value read + */ +Reader.prototype.fixed32 = function read_fixed32() { + + /* istanbul ignore if */ + if (this.pos + 4 > this.len) + throw indexOutOfRange(this, 4); + + return readFixed32_end(this.buf, this.pos += 4); +}; + +/** + * Reads fixed 32 bits as a signed 32 bit integer. + * @returns {number} Value read + */ +Reader.prototype.sfixed32 = function read_sfixed32() { + + /* istanbul ignore if */ + if (this.pos + 4 > this.len) + throw indexOutOfRange(this, 4); + + return readFixed32_end(this.buf, this.pos += 4) | 0; +}; + +/* eslint-disable no-invalid-this */ + +function readFixed64(/* this: Reader */) { + + /* istanbul ignore if */ + if (this.pos + 8 > this.len) + throw indexOutOfRange(this, 8); + + return new LongBits(readFixed32_end(this.buf, this.pos += 4), readFixed32_end(this.buf, this.pos += 4)); +} + +/* eslint-enable no-invalid-this */ + +/** + * Reads fixed 64 bits. + * @name Reader#fixed64 + * @function + * @returns {Long} Value read + */ + +/** + * Reads zig-zag encoded fixed 64 bits. + * @name Reader#sfixed64 + * @function + * @returns {Long} Value read + */ + +/** + * Reads a float (32 bit) as a number. + * @function + * @returns {number} Value read + */ +Reader.prototype.float = function read_float() { + + /* istanbul ignore if */ + if (this.pos + 4 > this.len) + throw indexOutOfRange(this, 4); + + var value = util.float.readFloatLE(this.buf, this.pos); + this.pos += 4; + return value; +}; + +/** + * Reads a double (64 bit float) as a number. + * @function + * @returns {number} Value read + */ +Reader.prototype.double = function read_double() { + + /* istanbul ignore if */ + if (this.pos + 8 > this.len) + throw indexOutOfRange(this, 4); + + var value = util.float.readDoubleLE(this.buf, this.pos); + this.pos += 8; + return value; +}; + +/** + * Reads a sequence of bytes preceeded by its length as a varint. + * @returns {Uint8Array} Value read + */ +Reader.prototype.bytes = function read_bytes() { + var length = this.uint32(), + start = this.pos, + end = this.pos + length; + + /* istanbul ignore if */ + if (end > this.len) + throw indexOutOfRange(this, length); + + this.pos += length; + if (Array.isArray(this.buf)) // plain array + return this.buf.slice(start, end); + return start === end // fix for IE 10/Win8 and others' subarray returning array of size 1 + ? new this.buf.constructor(0) + : this._slice.call(this.buf, start, end); +}; + +/** + * Reads a string preceeded by its byte length as a varint. + * @returns {string} Value read + */ +Reader.prototype.string = function read_string() { + var bytes = this.bytes(); + return utf8.read(bytes, 0, bytes.length); +}; + +/** + * Skips the specified number of bytes if specified, otherwise skips a varint. + * @param {number} [length] Length if known, otherwise a varint is assumed + * @returns {Reader} `this` + */ +Reader.prototype.skip = function skip(length) { + if (typeof length === "number") { + /* istanbul ignore if */ + if (this.pos + length > this.len) + throw indexOutOfRange(this, length); + this.pos += length; + } else { + do { + /* istanbul ignore if */ + if (this.pos >= this.len) + throw indexOutOfRange(this); + } while (this.buf[this.pos++] & 128); + } + return this; +}; + +/** + * Skips the next element of the specified wire type. + * @param {number} wireType Wire type received + * @returns {Reader} `this` + */ +Reader.prototype.skipType = function(wireType) { + switch (wireType) { + case 0: + this.skip(); + break; + case 1: + this.skip(8); + break; + case 2: + this.skip(this.uint32()); + break; + case 3: + do { // eslint-disable-line no-constant-condition + if ((wireType = this.uint32() & 7) === 4) + break; + this.skipType(wireType); + } while (true); + break; + case 5: + this.skip(4); + break; + + /* istanbul ignore next */ + default: + throw Error("invalid wire type " + wireType + " at offset " + this.pos); + } + return this; +}; + +Reader._configure = function(BufferReader_) { + BufferReader = BufferReader_; + + var fn = util.Long ? "toLong" : /* istanbul ignore next */ "toNumber"; + util.merge(Reader.prototype, { + + int64: function read_int64() { + return readLongVarint.call(this)[fn](false); + }, + + uint64: function read_uint64() { + return readLongVarint.call(this)[fn](true); + }, + + sint64: function read_sint64() { + return readLongVarint.call(this).zzDecode()[fn](false); + }, + + fixed64: function read_fixed64() { + return readFixed64.call(this)[fn](true); + }, + + sfixed64: function read_sfixed64() { + return readFixed64.call(this)[fn](false); + } + + }); +}; + + +/***/ }), +/* 182 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GPU_SUPPORT", function() { return GPU_SUPPORT; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_core_js_modules_es6_typed_array_buffer__ = __webpack_require__(183); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_core_js_modules_es6_typed_array_buffer___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_core_js_modules_es6_typed_array_buffer__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_core_js_modules_es6_typed_int8_array__ = __webpack_require__(184); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_core_js_modules_es6_typed_int8_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_core_js_modules_es6_typed_int8_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_core_js_modules_es6_typed_uint8_array__ = __webpack_require__(189); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_core_js_modules_es6_typed_uint8_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_core_js_modules_es6_typed_uint8_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_core_js_modules_es6_typed_uint8_clamped_array__ = __webpack_require__(190); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_core_js_modules_es6_typed_uint8_clamped_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_core_js_modules_es6_typed_uint8_clamped_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_core_js_modules_es6_typed_int16_array__ = __webpack_require__(191); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_core_js_modules_es6_typed_int16_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_core_js_modules_es6_typed_int16_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_core_js_modules_es6_typed_uint16_array__ = __webpack_require__(192); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_core_js_modules_es6_typed_uint16_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_core_js_modules_es6_typed_uint16_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_core_js_modules_es6_typed_int32_array__ = __webpack_require__(193); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_core_js_modules_es6_typed_int32_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_core_js_modules_es6_typed_int32_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_core_js_modules_es6_typed_uint32_array__ = __webpack_require__(194); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_core_js_modules_es6_typed_uint32_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_core_js_modules_es6_typed_uint32_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_core_js_modules_es6_typed_float32_array__ = __webpack_require__(195); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_core_js_modules_es6_typed_float32_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_core_js_modules_es6_typed_float32_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9_core_js_modules_es6_typed_float64_array__ = __webpack_require__(196); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9_core_js_modules_es6_typed_float64_array___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_9_core_js_modules_es6_typed_float64_array__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10_core_js_modules_es6_map__ = __webpack_require__(197); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10_core_js_modules_es6_map___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_10_core_js_modules_es6_map__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11_core_js_modules_es6_set__ = __webpack_require__(199); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11_core_js_modules_es6_set___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_11_core_js_modules_es6_set__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12_core_js_modules_es6_weak_map__ = __webpack_require__(200); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12_core_js_modules_es6_weak_map___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_12_core_js_modules_es6_weak_map__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13_core_js_modules_es6_weak_set__ = __webpack_require__(201); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13_core_js_modules_es6_weak_set___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_13_core_js_modules_es6_weak_set__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14_core_js_modules_es6_reflect_apply__ = __webpack_require__(202); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14_core_js_modules_es6_reflect_apply___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_14_core_js_modules_es6_reflect_apply__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15_core_js_modules_es6_reflect_construct__ = __webpack_require__(203); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15_core_js_modules_es6_reflect_construct___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_15_core_js_modules_es6_reflect_construct__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16_core_js_modules_es6_reflect_define_property__ = __webpack_require__(205); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16_core_js_modules_es6_reflect_define_property___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_16_core_js_modules_es6_reflect_define_property__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17_core_js_modules_es6_reflect_delete_property__ = __webpack_require__(206); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17_core_js_modules_es6_reflect_delete_property___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_17_core_js_modules_es6_reflect_delete_property__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_18_core_js_modules_es6_reflect_get__ = __webpack_require__(207); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_18_core_js_modules_es6_reflect_get___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_18_core_js_modules_es6_reflect_get__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_19_core_js_modules_es6_reflect_get_own_property_descriptor__ = __webpack_require__(208); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_19_core_js_modules_es6_reflect_get_own_property_descriptor___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_19_core_js_modules_es6_reflect_get_own_property_descriptor__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_20_core_js_modules_es6_reflect_get_prototype_of__ = __webpack_require__(209); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_20_core_js_modules_es6_reflect_get_prototype_of___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_20_core_js_modules_es6_reflect_get_prototype_of__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_21_core_js_modules_es6_reflect_has__ = __webpack_require__(210); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_21_core_js_modules_es6_reflect_has___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_21_core_js_modules_es6_reflect_has__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_22_core_js_modules_es6_reflect_is_extensible__ = __webpack_require__(211); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_22_core_js_modules_es6_reflect_is_extensible___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_22_core_js_modules_es6_reflect_is_extensible__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_23_core_js_modules_es6_reflect_own_keys__ = __webpack_require__(212); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_23_core_js_modules_es6_reflect_own_keys___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_23_core_js_modules_es6_reflect_own_keys__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_24_core_js_modules_es6_reflect_prevent_extensions__ = __webpack_require__(213); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_24_core_js_modules_es6_reflect_prevent_extensions___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_24_core_js_modules_es6_reflect_prevent_extensions__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_25_core_js_modules_es6_reflect_set__ = __webpack_require__(214); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_25_core_js_modules_es6_reflect_set___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_25_core_js_modules_es6_reflect_set__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_26_core_js_modules_es6_reflect_set_prototype_of__ = __webpack_require__(215); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_26_core_js_modules_es6_reflect_set_prototype_of___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_26_core_js_modules_es6_reflect_set_prototype_of__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_27_core_js_modules_es6_promise__ = __webpack_require__(216); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_27_core_js_modules_es6_promise___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_27_core_js_modules_es6_promise__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_28_core_js_modules_es6_symbol__ = __webpack_require__(220); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_28_core_js_modules_es6_symbol___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_28_core_js_modules_es6_symbol__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_29_core_js_modules_es6_object_freeze__ = __webpack_require__(223); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_29_core_js_modules_es6_object_freeze___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_29_core_js_modules_es6_object_freeze__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_30_core_js_modules_es6_object_seal__ = __webpack_require__(224); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_30_core_js_modules_es6_object_seal___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_30_core_js_modules_es6_object_seal__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_31_core_js_modules_es6_object_prevent_extensions__ = __webpack_require__(225); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_31_core_js_modules_es6_object_prevent_extensions___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_31_core_js_modules_es6_object_prevent_extensions__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_32_core_js_modules_es6_object_is_frozen__ = __webpack_require__(226); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_32_core_js_modules_es6_object_is_frozen___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_32_core_js_modules_es6_object_is_frozen__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_33_core_js_modules_es6_object_is_sealed__ = __webpack_require__(227); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_33_core_js_modules_es6_object_is_sealed___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_33_core_js_modules_es6_object_is_sealed__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_34_core_js_modules_es6_object_is_extensible__ = __webpack_require__(228); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_34_core_js_modules_es6_object_is_extensible___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_34_core_js_modules_es6_object_is_extensible__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_35_core_js_modules_es6_object_get_own_property_descriptor__ = __webpack_require__(229); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_35_core_js_modules_es6_object_get_own_property_descriptor___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_35_core_js_modules_es6_object_get_own_property_descriptor__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_36_core_js_modules_es6_object_get_prototype_of__ = __webpack_require__(230); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_36_core_js_modules_es6_object_get_prototype_of___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_36_core_js_modules_es6_object_get_prototype_of__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_37_core_js_modules_es6_object_keys__ = __webpack_require__(231); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_37_core_js_modules_es6_object_keys___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_37_core_js_modules_es6_object_keys__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_38_core_js_modules_es6_object_get_own_property_names__ = __webpack_require__(232); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_38_core_js_modules_es6_object_get_own_property_names___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_38_core_js_modules_es6_object_get_own_property_names__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_39_core_js_modules_es6_object_assign__ = __webpack_require__(233); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_39_core_js_modules_es6_object_assign___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_39_core_js_modules_es6_object_assign__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_40_core_js_modules_es6_object_is__ = __webpack_require__(234); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_40_core_js_modules_es6_object_is___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_40_core_js_modules_es6_object_is__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_41_core_js_modules_es6_object_set_prototype_of__ = __webpack_require__(236); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_41_core_js_modules_es6_object_set_prototype_of___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_41_core_js_modules_es6_object_set_prototype_of__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_42_core_js_modules_es6_function_name__ = __webpack_require__(237); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_42_core_js_modules_es6_function_name___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_42_core_js_modules_es6_function_name__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_43_core_js_modules_es6_string_raw__ = __webpack_require__(238); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_43_core_js_modules_es6_string_raw___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_43_core_js_modules_es6_string_raw__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_44_core_js_modules_es6_string_from_code_point__ = __webpack_require__(239); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_44_core_js_modules_es6_string_from_code_point___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_44_core_js_modules_es6_string_from_code_point__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_45_core_js_modules_es6_string_code_point_at__ = __webpack_require__(240); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_45_core_js_modules_es6_string_code_point_at___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_45_core_js_modules_es6_string_code_point_at__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_46_core_js_modules_es6_string_repeat__ = __webpack_require__(242); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_46_core_js_modules_es6_string_repeat___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_46_core_js_modules_es6_string_repeat__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_47_core_js_modules_es6_string_starts_with__ = __webpack_require__(243); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_47_core_js_modules_es6_string_starts_with___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_47_core_js_modules_es6_string_starts_with__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_48_core_js_modules_es6_string_ends_with__ = __webpack_require__(244); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_48_core_js_modules_es6_string_ends_with___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_48_core_js_modules_es6_string_ends_with__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_49_core_js_modules_es6_string_includes__ = __webpack_require__(245); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_49_core_js_modules_es6_string_includes___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_49_core_js_modules_es6_string_includes__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_50_core_js_modules_es6_regexp_flags__ = __webpack_require__(246); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_50_core_js_modules_es6_regexp_flags___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_50_core_js_modules_es6_regexp_flags__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_51_core_js_modules_es6_regexp_match__ = __webpack_require__(248); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_51_core_js_modules_es6_regexp_match___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_51_core_js_modules_es6_regexp_match__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_52_core_js_modules_es6_regexp_replace__ = __webpack_require__(249); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_52_core_js_modules_es6_regexp_replace___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_52_core_js_modules_es6_regexp_replace__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_53_core_js_modules_es6_regexp_split__ = __webpack_require__(250); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_53_core_js_modules_es6_regexp_split___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_53_core_js_modules_es6_regexp_split__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_54_core_js_modules_es6_regexp_search__ = __webpack_require__(251); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_54_core_js_modules_es6_regexp_search___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_54_core_js_modules_es6_regexp_search__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_55_core_js_modules_es6_array_from__ = __webpack_require__(252); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_55_core_js_modules_es6_array_from___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_55_core_js_modules_es6_array_from__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_56_core_js_modules_es6_array_of__ = __webpack_require__(253); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_56_core_js_modules_es6_array_of___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_56_core_js_modules_es6_array_of__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_57_core_js_modules_es6_array_copy_within__ = __webpack_require__(254); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_57_core_js_modules_es6_array_copy_within___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_57_core_js_modules_es6_array_copy_within__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_58_core_js_modules_es6_array_find__ = __webpack_require__(255); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_58_core_js_modules_es6_array_find___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_58_core_js_modules_es6_array_find__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_59_core_js_modules_es6_array_find_index__ = __webpack_require__(256); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_59_core_js_modules_es6_array_find_index___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_59_core_js_modules_es6_array_find_index__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_60_core_js_modules_es6_array_fill__ = __webpack_require__(257); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_60_core_js_modules_es6_array_fill___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_60_core_js_modules_es6_array_fill__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_61_core_js_modules_es6_array_iterator__ = __webpack_require__(96); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_61_core_js_modules_es6_array_iterator___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_61_core_js_modules_es6_array_iterator__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_62_core_js_modules_es6_number_is_finite__ = __webpack_require__(258); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_62_core_js_modules_es6_number_is_finite___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_62_core_js_modules_es6_number_is_finite__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_63_core_js_modules_es6_number_is_integer__ = __webpack_require__(259); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_63_core_js_modules_es6_number_is_integer___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_63_core_js_modules_es6_number_is_integer__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_64_core_js_modules_es6_number_is_safe_integer__ = __webpack_require__(260); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_64_core_js_modules_es6_number_is_safe_integer___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_64_core_js_modules_es6_number_is_safe_integer__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_65_core_js_modules_es6_number_is_nan__ = __webpack_require__(261); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_65_core_js_modules_es6_number_is_nan___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_65_core_js_modules_es6_number_is_nan__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_66_core_js_modules_es6_number_epsilon__ = __webpack_require__(262); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_66_core_js_modules_es6_number_epsilon___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_66_core_js_modules_es6_number_epsilon__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_67_core_js_modules_es6_number_min_safe_integer__ = __webpack_require__(263); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_67_core_js_modules_es6_number_min_safe_integer___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_67_core_js_modules_es6_number_min_safe_integer__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_68_core_js_modules_es6_number_max_safe_integer__ = __webpack_require__(264); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_68_core_js_modules_es6_number_max_safe_integer___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_68_core_js_modules_es6_number_max_safe_integer__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_69_core_js_modules_es6_number_parse_float__ = __webpack_require__(265); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_69_core_js_modules_es6_number_parse_float___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_69_core_js_modules_es6_number_parse_float__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_70_core_js_modules_es6_number_parse_int__ = __webpack_require__(267); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_70_core_js_modules_es6_number_parse_int___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_70_core_js_modules_es6_number_parse_int__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_71_core_js_modules_es6_math_acosh__ = __webpack_require__(269); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_71_core_js_modules_es6_math_acosh___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_71_core_js_modules_es6_math_acosh__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_72_core_js_modules_es6_math_asinh__ = __webpack_require__(270); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_72_core_js_modules_es6_math_asinh___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_72_core_js_modules_es6_math_asinh__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_73_core_js_modules_es6_math_atanh__ = __webpack_require__(271); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_73_core_js_modules_es6_math_atanh___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_73_core_js_modules_es6_math_atanh__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_74_core_js_modules_es6_math_cbrt__ = __webpack_require__(272); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_74_core_js_modules_es6_math_cbrt___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_74_core_js_modules_es6_math_cbrt__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_75_core_js_modules_es6_math_clz32__ = __webpack_require__(273); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_75_core_js_modules_es6_math_clz32___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_75_core_js_modules_es6_math_clz32__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_76_core_js_modules_es6_math_cosh__ = __webpack_require__(274); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_76_core_js_modules_es6_math_cosh___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_76_core_js_modules_es6_math_cosh__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_77_core_js_modules_es6_math_expm1__ = __webpack_require__(275); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_77_core_js_modules_es6_math_expm1___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_77_core_js_modules_es6_math_expm1__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_78_core_js_modules_es6_math_fround__ = __webpack_require__(276); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_78_core_js_modules_es6_math_fround___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_78_core_js_modules_es6_math_fround__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_79_core_js_modules_es6_math_hypot__ = __webpack_require__(278); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_79_core_js_modules_es6_math_hypot___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_79_core_js_modules_es6_math_hypot__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_80_core_js_modules_es6_math_imul__ = __webpack_require__(279); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_80_core_js_modules_es6_math_imul___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_80_core_js_modules_es6_math_imul__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_81_core_js_modules_es6_math_log1p__ = __webpack_require__(280); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_81_core_js_modules_es6_math_log1p___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_81_core_js_modules_es6_math_log1p__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_82_core_js_modules_es6_math_log10__ = __webpack_require__(281); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_82_core_js_modules_es6_math_log10___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_82_core_js_modules_es6_math_log10__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_83_core_js_modules_es6_math_log2__ = __webpack_require__(282); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_83_core_js_modules_es6_math_log2___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_83_core_js_modules_es6_math_log2__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_84_core_js_modules_es6_math_sign__ = __webpack_require__(283); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_84_core_js_modules_es6_math_sign___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_84_core_js_modules_es6_math_sign__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_85_core_js_modules_es6_math_sinh__ = __webpack_require__(284); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_85_core_js_modules_es6_math_sinh___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_85_core_js_modules_es6_math_sinh__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_86_core_js_modules_es6_math_tanh__ = __webpack_require__(285); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_86_core_js_modules_es6_math_tanh___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_86_core_js_modules_es6_math_tanh__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_87_core_js_modules_es6_math_trunc__ = __webpack_require__(286); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_87_core_js_modules_es6_math_trunc___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_87_core_js_modules_es6_math_trunc__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_88_core_js_modules_es7_array_includes__ = __webpack_require__(287); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_88_core_js_modules_es7_array_includes___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_88_core_js_modules_es7_array_includes__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_89_core_js_modules_es7_object_values__ = __webpack_require__(288); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_89_core_js_modules_es7_object_values___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_89_core_js_modules_es7_object_values__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_90_core_js_modules_es7_object_entries__ = __webpack_require__(289); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_90_core_js_modules_es7_object_entries___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_90_core_js_modules_es7_object_entries__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_91_core_js_modules_es7_object_get_own_property_descriptors__ = __webpack_require__(290); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_91_core_js_modules_es7_object_get_own_property_descriptors___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_91_core_js_modules_es7_object_get_own_property_descriptors__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_92_core_js_modules_es7_string_pad_start__ = __webpack_require__(291); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_92_core_js_modules_es7_string_pad_start___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_92_core_js_modules_es7_string_pad_start__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_93_core_js_modules_es7_string_pad_end__ = __webpack_require__(292); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_93_core_js_modules_es7_string_pad_end___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_93_core_js_modules_es7_string_pad_end__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_94_core_js_modules_web_timers__ = __webpack_require__(293); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_94_core_js_modules_web_timers___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_94_core_js_modules_web_timers__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_95_core_js_modules_web_immediate__ = __webpack_require__(294); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_95_core_js_modules_web_immediate___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_95_core_js_modules_web_immediate__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_96_core_js_modules_web_dom_iterable__ = __webpack_require__(295); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_96_core_js_modules_web_dom_iterable___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_96_core_js_modules_web_dom_iterable__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_97_regenerator_runtime_runtime__ = __webpack_require__(296); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_97_regenerator_runtime_runtime___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_97_regenerator_runtime_runtime__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_98__Model__ = __webpack_require__(297); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_99__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_100__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_101__activations__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_102__layers__ = __webpack_require__(114); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_103__utils_testUtils__ = __webpack_require__(560); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "Model", function() { return __WEBPACK_IMPORTED_MODULE_98__Model__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "Tensor", function() { return __WEBPACK_IMPORTED_MODULE_99__Tensor__["a"]; }); +/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, "activations", function() { return __WEBPACK_IMPORTED_MODULE_101__activations__; }); +/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, "layers", function() { return __WEBPACK_IMPORTED_MODULE_102__layers__; }); +/* harmony reexport (module object) */ __webpack_require__.d(__webpack_exports__, "testUtils", function() { return __WEBPACK_IMPORTED_MODULE_103__utils_testUtils__; }); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +var GPU_SUPPORT = __WEBPACK_IMPORTED_MODULE_100__WebGL2__["b" /* webgl2 */].isSupported; + + +/***/ }), +/* 183 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var $export = __webpack_require__(0); +var $typed = __webpack_require__(85); +var buffer = __webpack_require__(117); +var anObject = __webpack_require__(7); +var toAbsoluteIndex = __webpack_require__(46); +var toLength = __webpack_require__(12); +var isObject = __webpack_require__(5); +var ArrayBuffer = __webpack_require__(6).ArrayBuffer; +var speciesConstructor = __webpack_require__(92); +var $ArrayBuffer = buffer.ArrayBuffer; +var $DataView = buffer.DataView; +var $isView = $typed.ABV && ArrayBuffer.isView; +var $slice = $ArrayBuffer.prototype.slice; +var VIEW = $typed.VIEW; +var ARRAY_BUFFER = 'ArrayBuffer'; + +$export($export.G + $export.W + $export.F * (ArrayBuffer !== $ArrayBuffer), { ArrayBuffer: $ArrayBuffer }); + +$export($export.S + $export.F * !$typed.CONSTR, ARRAY_BUFFER, { + // 24.1.3.1 ArrayBuffer.isView(arg) + isView: function isView(it) { + return $isView && $isView(it) || isObject(it) && VIEW in it; + } +}); + +$export($export.P + $export.U + $export.F * __webpack_require__(8)(function () { + return !new $ArrayBuffer(2).slice(1, undefined).byteLength; +}), ARRAY_BUFFER, { + // 24.1.4.3 ArrayBuffer.prototype.slice(start, end) + slice: function slice(start, end) { + if ($slice !== undefined && end === undefined) return $slice.call(anObject(this), start); // FF fix + var len = anObject(this).byteLength; + var first = toAbsoluteIndex(start, len); + var final = toAbsoluteIndex(end === undefined ? len : end, len); + var result = new (speciesConstructor(this, $ArrayBuffer))(toLength(final - first)); + var viewS = new $DataView(this); + var viewT = new $DataView(result); + var index = 0; + while (first < final) { + viewT.setUint8(index++, viewS.getUint8(first++)); + } return result; + } +}); + +__webpack_require__(68)(ARRAY_BUFFER); + + +/***/ }), +/* 184 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Int8', 1, function (init) { + return function Int8Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}); + + +/***/ }), +/* 185 */ +/***/ (function(module, exports, __webpack_require__) { + +var dP = __webpack_require__(10); +var anObject = __webpack_require__(7); +var getKeys = __webpack_require__(37); + +module.exports = __webpack_require__(13) ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var keys = getKeys(Properties); + var length = keys.length; + var i = 0; + var P; + while (length > i) dP.f(O, P = keys[i++], Properties[P]); + return O; +}; + + +/***/ }), +/* 186 */ +/***/ (function(module, exports, __webpack_require__) { + +// 9.4.2.3 ArraySpeciesCreate(originalArray, length) +var speciesConstructor = __webpack_require__(187); + +module.exports = function (original, length) { + return new (speciesConstructor(original))(length); +}; + + +/***/ }), +/* 187 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(5); +var isArray = __webpack_require__(121); +var SPECIES = __webpack_require__(9)('species'); + +module.exports = function (original) { + var C; + if (isArray(original)) { + C = original.constructor; + // cross-realm fallback + if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined; + if (isObject(C)) { + C = C[SPECIES]; + if (C === null) C = undefined; + } + } return C === undefined ? Array : C; +}; + + +/***/ }), +/* 188 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var create = __webpack_require__(56); +var descriptor = __webpack_require__(33); +var setToStringTag = __webpack_require__(47); +var IteratorPrototype = {}; + +// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() +__webpack_require__(16)(IteratorPrototype, __webpack_require__(9)('iterator'), function () { return this; }); + +module.exports = function (Constructor, NAME, next) { + Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) }); + setToStringTag(Constructor, NAME + ' Iterator'); +}; + + +/***/ }), +/* 189 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Uint8', 1, function (init) { + return function Uint8Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}); + + +/***/ }), +/* 190 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Uint8', 1, function (init) { + return function Uint8ClampedArray(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}, true); + + +/***/ }), +/* 191 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Int16', 2, function (init) { + return function Int16Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}); + + +/***/ }), +/* 192 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Uint16', 2, function (init) { + return function Uint16Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}); + + +/***/ }), +/* 193 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Int32', 4, function (init) { + return function Int32Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}); + + +/***/ }), +/* 194 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Uint32', 4, function (init) { + return function Uint32Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}); + + +/***/ }), +/* 195 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Float32', 4, function (init) { + return function Float32Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}); + + +/***/ }), +/* 196 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(25)('Float64', 8, function (init) { + return function Float64Array(data, byteOffset, length) { + return init(this, data, byteOffset, length); + }; +}); + + +/***/ }), +/* 197 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var strong = __webpack_require__(125); +var validate = __webpack_require__(51); +var MAP = 'Map'; + +// 23.1 Map Objects +module.exports = __webpack_require__(71)(MAP, function (get) { + return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; +}, { + // 23.1.3.6 Map.prototype.get(key) + get: function get(key) { + var entry = strong.getEntry(validate(this, MAP), key); + return entry && entry.v; + }, + // 23.1.3.9 Map.prototype.set(key, value) + set: function set(key, value) { + return strong.def(validate(this, MAP), key === 0 ? 0 : key, value); + } +}, strong, true); + + +/***/ }), +/* 198 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(5); +var setPrototypeOf = __webpack_require__(97).set; +module.exports = function (that, target, C) { + var S = target.constructor; + var P; + if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) { + setPrototypeOf(that, P); + } return that; +}; + + +/***/ }), +/* 199 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var strong = __webpack_require__(125); +var validate = __webpack_require__(51); +var SET = 'Set'; + +// 23.2 Set Objects +module.exports = __webpack_require__(71)(SET, function (get) { + return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; +}, { + // 23.2.3.1 Set.prototype.add(value) + add: function add(value) { + return strong.def(validate(this, SET), value = value === 0 ? 0 : value, value); + } +}, strong); + + +/***/ }), +/* 200 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var each = __webpack_require__(57)(0); +var redefine = __webpack_require__(29); +var meta = __webpack_require__(31); +var assign = __webpack_require__(127); +var weak = __webpack_require__(128); +var isObject = __webpack_require__(5); +var fails = __webpack_require__(8); +var validate = __webpack_require__(51); +var WEAK_MAP = 'WeakMap'; +var getWeak = meta.getWeak; +var isExtensible = Object.isExtensible; +var uncaughtFrozenStore = weak.ufstore; +var tmp = {}; +var InternalMap; + +var wrapper = function (get) { + return function WeakMap() { + return get(this, arguments.length > 0 ? arguments[0] : undefined); + }; +}; + +var methods = { + // 23.3.3.3 WeakMap.prototype.get(key) + get: function get(key) { + if (isObject(key)) { + var data = getWeak(key); + if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key); + return data ? data[this._i] : undefined; + } + }, + // 23.3.3.5 WeakMap.prototype.set(key, value) + set: function set(key, value) { + return weak.def(validate(this, WEAK_MAP), key, value); + } +}; + +// 23.3 WeakMap Objects +var $WeakMap = module.exports = __webpack_require__(71)(WEAK_MAP, wrapper, methods, weak, true, true); + +// IE11 WeakMap frozen keys fix +if (fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) { + InternalMap = weak.getConstructor(wrapper, WEAK_MAP); + assign(InternalMap.prototype, methods); + meta.NEED = true; + each(['delete', 'has', 'get', 'set'], function (key) { + var proto = $WeakMap.prototype; + var method = proto[key]; + redefine(proto, key, function (a, b) { + // store frozen objects on internal weakmap shim + if (isObject(a) && !isExtensible(a)) { + if (!this._f) this._f = new InternalMap(); + var result = this._f[key](a, b); + return key == 'set' ? this : result; + // store all the rest on native weakmap + } return method.call(this, a, b); + }); + }); +} + + +/***/ }), +/* 201 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var weak = __webpack_require__(128); +var validate = __webpack_require__(51); +var WEAK_SET = 'WeakSet'; + +// 23.4 WeakSet Objects +__webpack_require__(71)(WEAK_SET, function (get) { + return function WeakSet() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; +}, { + // 23.4.3.1 WeakSet.prototype.add(value) + add: function add(value) { + return weak.def(validate(this, WEAK_SET), value, true); + } +}, weak, false, true); + + +/***/ }), +/* 202 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.1 Reflect.apply(target, thisArgument, argumentsList) +var $export = __webpack_require__(0); +var aFunction = __webpack_require__(35); +var anObject = __webpack_require__(7); +var rApply = (__webpack_require__(6).Reflect || {}).apply; +var fApply = Function.apply; +// MS Edge argumentsList argument is optional +$export($export.S + $export.F * !__webpack_require__(8)(function () { + rApply(function () { /* empty */ }); +}), 'Reflect', { + apply: function apply(target, thisArgument, argumentsList) { + var T = aFunction(target); + var L = anObject(argumentsList); + return rApply ? rApply(T, thisArgument, L) : fApply.call(T, thisArgument, L); + } +}); + + +/***/ }), +/* 203 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.2 Reflect.construct(target, argumentsList [, newTarget]) +var $export = __webpack_require__(0); +var create = __webpack_require__(56); +var aFunction = __webpack_require__(35); +var anObject = __webpack_require__(7); +var isObject = __webpack_require__(5); +var fails = __webpack_require__(8); +var bind = __webpack_require__(204); +var rConstruct = (__webpack_require__(6).Reflect || {}).construct; + +// MS Edge supports only 2 arguments and argumentsList argument is optional +// FF Nightly sets third argument as `new.target`, but does not create `this` from it +var NEW_TARGET_BUG = fails(function () { + function F() { /* empty */ } + return !(rConstruct(function () { /* empty */ }, [], F) instanceof F); +}); +var ARGS_BUG = !fails(function () { + rConstruct(function () { /* empty */ }); +}); + +$export($export.S + $export.F * (NEW_TARGET_BUG || ARGS_BUG), 'Reflect', { + construct: function construct(Target, args /* , newTarget */) { + aFunction(Target); + anObject(args); + var newTarget = arguments.length < 3 ? Target : aFunction(arguments[2]); + if (ARGS_BUG && !NEW_TARGET_BUG) return rConstruct(Target, args, newTarget); + if (Target == newTarget) { + // w/o altered newTarget, optimization for 0-4 arguments + switch (args.length) { + case 0: return new Target(); + case 1: return new Target(args[0]); + case 2: return new Target(args[0], args[1]); + case 3: return new Target(args[0], args[1], args[2]); + case 4: return new Target(args[0], args[1], args[2], args[3]); + } + // w/o altered newTarget, lot of arguments case + var $args = [null]; + $args.push.apply($args, args); + return new (bind.apply(Target, $args))(); + } + // with altered newTarget, not support built-in constructors + var proto = newTarget.prototype; + var instance = create(isObject(proto) ? proto : Object.prototype); + var result = Function.apply.call(Target, instance, args); + return isObject(result) ? result : instance; + } +}); + + +/***/ }), +/* 204 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var aFunction = __webpack_require__(35); +var isObject = __webpack_require__(5); +var invoke = __webpack_require__(129); +var arraySlice = [].slice; +var factories = {}; + +var construct = function (F, len, args) { + if (!(len in factories)) { + for (var n = [], i = 0; i < len; i++) n[i] = 'a[' + i + ']'; + // eslint-disable-next-line no-new-func + factories[len] = Function('F,a', 'return new F(' + n.join(',') + ')'); + } return factories[len](F, args); +}; + +module.exports = Function.bind || function bind(that /* , ...args */) { + var fn = aFunction(this); + var partArgs = arraySlice.call(arguments, 1); + var bound = function (/* args... */) { + var args = partArgs.concat(arraySlice.call(arguments)); + return this instanceof bound ? construct(fn, args.length, args) : invoke(fn, args, that); + }; + if (isObject(fn.prototype)) bound.prototype = fn.prototype; + return bound; +}; + + +/***/ }), +/* 205 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.3 Reflect.defineProperty(target, propertyKey, attributes) +var dP = __webpack_require__(10); +var $export = __webpack_require__(0); +var anObject = __webpack_require__(7); +var toPrimitive = __webpack_require__(54); + +// MS Edge has broken Reflect.defineProperty - throwing instead of returning false +$export($export.S + $export.F * __webpack_require__(8)(function () { + // eslint-disable-next-line no-undef + Reflect.defineProperty(dP.f({}, 1, { value: 1 }), 1, { value: 2 }); +}), 'Reflect', { + defineProperty: function defineProperty(target, propertyKey, attributes) { + anObject(target); + propertyKey = toPrimitive(propertyKey, true); + anObject(attributes); + try { + dP.f(target, propertyKey, attributes); + return true; + } catch (e) { + return false; + } + } +}); + + +/***/ }), +/* 206 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.4 Reflect.deleteProperty(target, propertyKey) +var $export = __webpack_require__(0); +var gOPD = __webpack_require__(26).f; +var anObject = __webpack_require__(7); + +$export($export.S, 'Reflect', { + deleteProperty: function deleteProperty(target, propertyKey) { + var desc = gOPD(anObject(target), propertyKey); + return desc && !desc.configurable ? false : delete target[propertyKey]; + } +}); + + +/***/ }), +/* 207 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.6 Reflect.get(target, propertyKey [, receiver]) +var gOPD = __webpack_require__(26); +var getPrototypeOf = __webpack_require__(49); +var has = __webpack_require__(14); +var $export = __webpack_require__(0); +var isObject = __webpack_require__(5); +var anObject = __webpack_require__(7); + +function get(target, propertyKey /* , receiver */) { + var receiver = arguments.length < 3 ? target : arguments[2]; + var desc, proto; + if (anObject(target) === receiver) return target[propertyKey]; + if (desc = gOPD.f(target, propertyKey)) return has(desc, 'value') + ? desc.value + : desc.get !== undefined + ? desc.get.call(receiver) + : undefined; + if (isObject(proto = getPrototypeOf(target))) return get(proto, propertyKey, receiver); +} + +$export($export.S, 'Reflect', { get: get }); + + +/***/ }), +/* 208 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.7 Reflect.getOwnPropertyDescriptor(target, propertyKey) +var gOPD = __webpack_require__(26); +var $export = __webpack_require__(0); +var anObject = __webpack_require__(7); + +$export($export.S, 'Reflect', { + getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, propertyKey) { + return gOPD.f(anObject(target), propertyKey); + } +}); + + +/***/ }), +/* 209 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.8 Reflect.getPrototypeOf(target) +var $export = __webpack_require__(0); +var getProto = __webpack_require__(49); +var anObject = __webpack_require__(7); + +$export($export.S, 'Reflect', { + getPrototypeOf: function getPrototypeOf(target) { + return getProto(anObject(target)); + } +}); + + +/***/ }), +/* 210 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.9 Reflect.has(target, propertyKey) +var $export = __webpack_require__(0); + +$export($export.S, 'Reflect', { + has: function has(target, propertyKey) { + return propertyKey in target; + } +}); + + +/***/ }), +/* 211 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.10 Reflect.isExtensible(target) +var $export = __webpack_require__(0); +var anObject = __webpack_require__(7); +var $isExtensible = Object.isExtensible; + +$export($export.S, 'Reflect', { + isExtensible: function isExtensible(target) { + anObject(target); + return $isExtensible ? $isExtensible(target) : true; + } +}); + + +/***/ }), +/* 212 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.11 Reflect.ownKeys(target) +var $export = __webpack_require__(0); + +$export($export.S, 'Reflect', { ownKeys: __webpack_require__(130) }); + + +/***/ }), +/* 213 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.12 Reflect.preventExtensions(target) +var $export = __webpack_require__(0); +var anObject = __webpack_require__(7); +var $preventExtensions = Object.preventExtensions; + +$export($export.S, 'Reflect', { + preventExtensions: function preventExtensions(target) { + anObject(target); + try { + if ($preventExtensions) $preventExtensions(target); + return true; + } catch (e) { + return false; + } + } +}); + + +/***/ }), +/* 214 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.13 Reflect.set(target, propertyKey, V [, receiver]) +var dP = __webpack_require__(10); +var gOPD = __webpack_require__(26); +var getPrototypeOf = __webpack_require__(49); +var has = __webpack_require__(14); +var $export = __webpack_require__(0); +var createDesc = __webpack_require__(33); +var anObject = __webpack_require__(7); +var isObject = __webpack_require__(5); + +function set(target, propertyKey, V /* , receiver */) { + var receiver = arguments.length < 4 ? target : arguments[3]; + var ownDesc = gOPD.f(anObject(target), propertyKey); + var existingDescriptor, proto; + if (!ownDesc) { + if (isObject(proto = getPrototypeOf(target))) { + return set(proto, propertyKey, V, receiver); + } + ownDesc = createDesc(0); + } + if (has(ownDesc, 'value')) { + if (ownDesc.writable === false || !isObject(receiver)) return false; + existingDescriptor = gOPD.f(receiver, propertyKey) || createDesc(0); + existingDescriptor.value = V; + dP.f(receiver, propertyKey, existingDescriptor); + return true; + } + return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true); +} + +$export($export.S, 'Reflect', { set: set }); + + +/***/ }), +/* 215 */ +/***/ (function(module, exports, __webpack_require__) { + +// 26.1.14 Reflect.setPrototypeOf(target, proto) +var $export = __webpack_require__(0); +var setProto = __webpack_require__(97); + +if (setProto) $export($export.S, 'Reflect', { + setPrototypeOf: function setPrototypeOf(target, proto) { + setProto.check(target, proto); + try { + setProto.set(target, proto); + return true; + } catch (e) { + return false; + } + } +}); + + +/***/ }), +/* 216 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var LIBRARY = __webpack_require__(42); +var global = __webpack_require__(6); +var ctx = __webpack_require__(23); +var classof = __webpack_require__(93); +var $export = __webpack_require__(0); +var isObject = __webpack_require__(5); +var aFunction = __webpack_require__(35); +var anInstance = __webpack_require__(44); +var forOf = __webpack_require__(70); +var speciesConstructor = __webpack_require__(92); +var task = __webpack_require__(98).set; +var microtask = __webpack_require__(217)(); +var newPromiseCapabilityModule = __webpack_require__(131); +var perform = __webpack_require__(218); +var promiseResolve = __webpack_require__(219); +var PROMISE = 'Promise'; +var TypeError = global.TypeError; +var process = global.process; +var $Promise = global[PROMISE]; +var isNode = classof(process) == 'process'; +var empty = function () { /* empty */ }; +var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper; +var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f; + +var USE_NATIVE = !!function () { + try { + // correct subclassing with @@species support + var promise = $Promise.resolve(1); + var FakePromise = (promise.constructor = {})[__webpack_require__(9)('species')] = function (exec) { + exec(empty, empty); + }; + // unhandled rejections tracking support, NodeJS Promise without it fails @@species test + return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; + } catch (e) { /* empty */ } +}(); + +// helpers +var isThenable = function (it) { + var then; + return isObject(it) && typeof (then = it.then) == 'function' ? then : false; +}; +var notify = function (promise, isReject) { + if (promise._n) return; + promise._n = true; + var chain = promise._c; + microtask(function () { + var value = promise._v; + var ok = promise._s == 1; + var i = 0; + var run = function (reaction) { + var handler = ok ? reaction.ok : reaction.fail; + var resolve = reaction.resolve; + var reject = reaction.reject; + var domain = reaction.domain; + var result, then; + try { + if (handler) { + if (!ok) { + if (promise._h == 2) onHandleUnhandled(promise); + promise._h = 1; + } + if (handler === true) result = value; + else { + if (domain) domain.enter(); + result = handler(value); + if (domain) domain.exit(); + } + if (result === reaction.promise) { + reject(TypeError('Promise-chain cycle')); + } else if (then = isThenable(result)) { + then.call(result, resolve, reject); + } else resolve(result); + } else reject(value); + } catch (e) { + reject(e); + } + }; + while (chain.length > i) run(chain[i++]); // variable length - can't use forEach + promise._c = []; + promise._n = false; + if (isReject && !promise._h) onUnhandled(promise); + }); +}; +var onUnhandled = function (promise) { + task.call(global, function () { + var value = promise._v; + var unhandled = isUnhandled(promise); + var result, handler, console; + if (unhandled) { + result = perform(function () { + if (isNode) { + process.emit('unhandledRejection', value, promise); + } else if (handler = global.onunhandledrejection) { + handler({ promise: promise, reason: value }); + } else if ((console = global.console) && console.error) { + console.error('Unhandled promise rejection', value); + } + }); + // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should + promise._h = isNode || isUnhandled(promise) ? 2 : 1; + } promise._a = undefined; + if (unhandled && result.e) throw result.v; + }); +}; +var isUnhandled = function (promise) { + if (promise._h == 1) return false; + var chain = promise._a || promise._c; + var i = 0; + var reaction; + while (chain.length > i) { + reaction = chain[i++]; + if (reaction.fail || !isUnhandled(reaction.promise)) return false; + } return true; +}; +var onHandleUnhandled = function (promise) { + task.call(global, function () { + var handler; + if (isNode) { + process.emit('rejectionHandled', promise); + } else if (handler = global.onrejectionhandled) { + handler({ promise: promise, reason: promise._v }); + } + }); +}; +var $reject = function (value) { + var promise = this; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + promise._v = value; + promise._s = 2; + if (!promise._a) promise._a = promise._c.slice(); + notify(promise, true); +}; +var $resolve = function (value) { + var promise = this; + var then; + if (promise._d) return; + promise._d = true; + promise = promise._w || promise; // unwrap + try { + if (promise === value) throw TypeError("Promise can't be resolved itself"); + if (then = isThenable(value)) { + microtask(function () { + var wrapper = { _w: promise, _d: false }; // wrap + try { + then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); + } catch (e) { + $reject.call(wrapper, e); + } + }); + } else { + promise._v = value; + promise._s = 1; + notify(promise, false); + } + } catch (e) { + $reject.call({ _w: promise, _d: false }, e); // wrap + } +}; + +// constructor polyfill +if (!USE_NATIVE) { + // 25.4.3.1 Promise(executor) + $Promise = function Promise(executor) { + anInstance(this, $Promise, PROMISE, '_h'); + aFunction(executor); + Internal.call(this); + try { + executor(ctx($resolve, this, 1), ctx($reject, this, 1)); + } catch (err) { + $reject.call(this, err); + } + }; + // eslint-disable-next-line no-unused-vars + Internal = function Promise(executor) { + this._c = []; // <- awaiting reactions + this._a = undefined; // <- checked in isUnhandled reactions + this._s = 0; // <- state + this._d = false; // <- done + this._v = undefined; // <- value + this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled + this._n = false; // <- notify + }; + Internal.prototype = __webpack_require__(43)($Promise.prototype, { + // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) + then: function then(onFulfilled, onRejected) { + var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); + reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; + reaction.fail = typeof onRejected == 'function' && onRejected; + reaction.domain = isNode ? process.domain : undefined; + this._c.push(reaction); + if (this._a) this._a.push(reaction); + if (this._s) notify(this, false); + return reaction.promise; + }, + // 25.4.5.1 Promise.prototype.catch(onRejected) + 'catch': function (onRejected) { + return this.then(undefined, onRejected); + } + }); + OwnPromiseCapability = function () { + var promise = new Internal(); + this.promise = promise; + this.resolve = ctx($resolve, promise, 1); + this.reject = ctx($reject, promise, 1); + }; + newPromiseCapabilityModule.f = newPromiseCapability = function (C) { + return C === $Promise || C === Wrapper + ? new OwnPromiseCapability(C) + : newGenericPromiseCapability(C); + }; +} + +$export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise }); +__webpack_require__(47)($Promise, PROMISE); +__webpack_require__(68)(PROMISE); +Wrapper = __webpack_require__(41)[PROMISE]; + +// statics +$export($export.S + $export.F * !USE_NATIVE, PROMISE, { + // 25.4.4.5 Promise.reject(r) + reject: function reject(r) { + var capability = newPromiseCapability(this); + var $$reject = capability.reject; + $$reject(r); + return capability.promise; + } +}); +$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { + // 25.4.4.6 Promise.resolve(x) + resolve: function resolve(x) { + return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x); + } +}); +$export($export.S + $export.F * !(USE_NATIVE && __webpack_require__(69)(function (iter) { + $Promise.all(iter)['catch'](empty); +})), PROMISE, { + // 25.4.4.1 Promise.all(iterable) + all: function all(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var resolve = capability.resolve; + var reject = capability.reject; + var result = perform(function () { + var values = []; + var index = 0; + var remaining = 1; + forOf(iterable, false, function (promise) { + var $index = index++; + var alreadyCalled = false; + values.push(undefined); + remaining++; + C.resolve(promise).then(function (value) { + if (alreadyCalled) return; + alreadyCalled = true; + values[$index] = value; + --remaining || resolve(values); + }, reject); + }); + --remaining || resolve(values); + }); + if (result.e) reject(result.v); + return capability.promise; + }, + // 25.4.4.4 Promise.race(iterable) + race: function race(iterable) { + var C = this; + var capability = newPromiseCapability(C); + var reject = capability.reject; + var result = perform(function () { + forOf(iterable, false, function (promise) { + C.resolve(promise).then(capability.resolve, reject); + }); + }); + if (result.e) reject(result.v); + return capability.promise; + } +}); + + +/***/ }), +/* 217 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(6); +var macrotask = __webpack_require__(98).set; +var Observer = global.MutationObserver || global.WebKitMutationObserver; +var process = global.process; +var Promise = global.Promise; +var isNode = __webpack_require__(45)(process) == 'process'; + +module.exports = function () { + var head, last, notify; + + var flush = function () { + var parent, fn; + if (isNode && (parent = process.domain)) parent.exit(); + while (head) { + fn = head.fn; + head = head.next; + try { + fn(); + } catch (e) { + if (head) notify(); + else last = undefined; + throw e; + } + } last = undefined; + if (parent) parent.enter(); + }; + + // Node.js + if (isNode) { + notify = function () { + process.nextTick(flush); + }; + // browsers with MutationObserver + } else if (Observer) { + var toggle = true; + var node = document.createTextNode(''); + new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new + notify = function () { + node.data = toggle = !toggle; + }; + // environments with maybe non-completely correct, but existent Promise + } else if (Promise && Promise.resolve) { + var promise = Promise.resolve(); + notify = function () { + promise.then(flush); + }; + // for other environments - macrotask based on: + // - setImmediate + // - MessageChannel + // - window.postMessag + // - onreadystatechange + // - setTimeout + } else { + notify = function () { + // strange IE + webpack dev server bug - use .call(global) + macrotask.call(global, flush); + }; + } + + return function (fn) { + var task = { fn: fn, next: undefined }; + if (last) last.next = task; + if (!head) { + head = task; + notify(); + } last = task; + }; +}; + + +/***/ }), +/* 218 */ +/***/ (function(module, exports) { + +module.exports = function (exec) { + try { + return { e: false, v: exec() }; + } catch (e) { + return { e: true, v: e }; + } +}; + + +/***/ }), +/* 219 */ +/***/ (function(module, exports, __webpack_require__) { + +var anObject = __webpack_require__(7); +var isObject = __webpack_require__(5); +var newPromiseCapability = __webpack_require__(131); + +module.exports = function (C, x) { + anObject(C); + if (isObject(x) && x.constructor === C) return x; + var promiseCapability = newPromiseCapability.f(C); + var resolve = promiseCapability.resolve; + resolve(x); + return promiseCapability.promise; +}; + + +/***/ }), +/* 220 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// ECMAScript 6 symbols shim +var global = __webpack_require__(6); +var has = __webpack_require__(14); +var DESCRIPTORS = __webpack_require__(13); +var $export = __webpack_require__(0); +var redefine = __webpack_require__(29); +var META = __webpack_require__(31).KEY; +var $fails = __webpack_require__(8); +var shared = __webpack_require__(89); +var setToStringTag = __webpack_require__(47); +var uid = __webpack_require__(34); +var wks = __webpack_require__(9); +var wksExt = __webpack_require__(132); +var wksDefine = __webpack_require__(221); +var enumKeys = __webpack_require__(222); +var isArray = __webpack_require__(121); +var anObject = __webpack_require__(7); +var toIObject = __webpack_require__(20); +var toPrimitive = __webpack_require__(54); +var createDesc = __webpack_require__(33); +var _create = __webpack_require__(56); +var gOPNExt = __webpack_require__(133); +var $GOPD = __webpack_require__(26); +var $DP = __webpack_require__(10); +var $keys = __webpack_require__(37); +var gOPD = $GOPD.f; +var dP = $DP.f; +var gOPN = gOPNExt.f; +var $Symbol = global.Symbol; +var $JSON = global.JSON; +var _stringify = $JSON && $JSON.stringify; +var PROTOTYPE = 'prototype'; +var HIDDEN = wks('_hidden'); +var TO_PRIMITIVE = wks('toPrimitive'); +var isEnum = {}.propertyIsEnumerable; +var SymbolRegistry = shared('symbol-registry'); +var AllSymbols = shared('symbols'); +var OPSymbols = shared('op-symbols'); +var ObjectProto = Object[PROTOTYPE]; +var USE_NATIVE = typeof $Symbol == 'function'; +var QObject = global.QObject; +// Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173 +var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild; + +// fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687 +var setSymbolDesc = DESCRIPTORS && $fails(function () { + return _create(dP({}, 'a', { + get: function () { return dP(this, 'a', { value: 7 }).a; } + })).a != 7; +}) ? function (it, key, D) { + var protoDesc = gOPD(ObjectProto, key); + if (protoDesc) delete ObjectProto[key]; + dP(it, key, D); + if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc); +} : dP; + +var wrap = function (tag) { + var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]); + sym._k = tag; + return sym; +}; + +var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function (it) { + return typeof it == 'symbol'; +} : function (it) { + return it instanceof $Symbol; +}; + +var $defineProperty = function defineProperty(it, key, D) { + if (it === ObjectProto) $defineProperty(OPSymbols, key, D); + anObject(it); + key = toPrimitive(key, true); + anObject(D); + if (has(AllSymbols, key)) { + if (!D.enumerable) { + if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {})); + it[HIDDEN][key] = true; + } else { + if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false; + D = _create(D, { enumerable: createDesc(0, false) }); + } return setSymbolDesc(it, key, D); + } return dP(it, key, D); +}; +var $defineProperties = function defineProperties(it, P) { + anObject(it); + var keys = enumKeys(P = toIObject(P)); + var i = 0; + var l = keys.length; + var key; + while (l > i) $defineProperty(it, key = keys[i++], P[key]); + return it; +}; +var $create = function create(it, P) { + return P === undefined ? _create(it) : $defineProperties(_create(it), P); +}; +var $propertyIsEnumerable = function propertyIsEnumerable(key) { + var E = isEnum.call(this, key = toPrimitive(key, true)); + if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false; + return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true; +}; +var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) { + it = toIObject(it); + key = toPrimitive(key, true); + if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return; + var D = gOPD(it, key); + if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true; + return D; +}; +var $getOwnPropertyNames = function getOwnPropertyNames(it) { + var names = gOPN(toIObject(it)); + var result = []; + var i = 0; + var key; + while (names.length > i) { + if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key); + } return result; +}; +var $getOwnPropertySymbols = function getOwnPropertySymbols(it) { + var IS_OP = it === ObjectProto; + var names = gOPN(IS_OP ? OPSymbols : toIObject(it)); + var result = []; + var i = 0; + var key; + while (names.length > i) { + if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]); + } return result; +}; + +// 19.4.1.1 Symbol([description]) +if (!USE_NATIVE) { + $Symbol = function Symbol() { + if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!'); + var tag = uid(arguments.length > 0 ? arguments[0] : undefined); + var $set = function (value) { + if (this === ObjectProto) $set.call(OPSymbols, value); + if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false; + setSymbolDesc(this, tag, createDesc(1, value)); + }; + if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, { configurable: true, set: $set }); + return wrap(tag); + }; + redefine($Symbol[PROTOTYPE], 'toString', function toString() { + return this._k; + }); + + $GOPD.f = $getOwnPropertyDescriptor; + $DP.f = $defineProperty; + __webpack_require__(55).f = gOPNExt.f = $getOwnPropertyNames; + __webpack_require__(58).f = $propertyIsEnumerable; + __webpack_require__(72).f = $getOwnPropertySymbols; + + if (DESCRIPTORS && !__webpack_require__(42)) { + redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true); + } + + wksExt.f = function (name) { + return wrap(wks(name)); + }; +} + +$export($export.G + $export.W + $export.F * !USE_NATIVE, { Symbol: $Symbol }); + +for (var es6Symbols = ( + // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14 + 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables' +).split(','), j = 0; es6Symbols.length > j;)wks(es6Symbols[j++]); + +for (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) wksDefine(wellKnownSymbols[k++]); + +$export($export.S + $export.F * !USE_NATIVE, 'Symbol', { + // 19.4.2.1 Symbol.for(key) + 'for': function (key) { + return has(SymbolRegistry, key += '') + ? SymbolRegistry[key] + : SymbolRegistry[key] = $Symbol(key); + }, + // 19.4.2.5 Symbol.keyFor(sym) + keyFor: function keyFor(sym) { + if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!'); + for (var key in SymbolRegistry) if (SymbolRegistry[key] === sym) return key; + }, + useSetter: function () { setter = true; }, + useSimple: function () { setter = false; } +}); + +$export($export.S + $export.F * !USE_NATIVE, 'Object', { + // 19.1.2.2 Object.create(O [, Properties]) + create: $create, + // 19.1.2.4 Object.defineProperty(O, P, Attributes) + defineProperty: $defineProperty, + // 19.1.2.3 Object.defineProperties(O, Properties) + defineProperties: $defineProperties, + // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) + getOwnPropertyDescriptor: $getOwnPropertyDescriptor, + // 19.1.2.7 Object.getOwnPropertyNames(O) + getOwnPropertyNames: $getOwnPropertyNames, + // 19.1.2.8 Object.getOwnPropertySymbols(O) + getOwnPropertySymbols: $getOwnPropertySymbols +}); + +// 24.3.2 JSON.stringify(value [, replacer [, space]]) +$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () { + var S = $Symbol(); + // MS Edge converts symbol values to JSON as {} + // WebKit converts symbol values to JSON as null + // V8 throws on boxed symbols + return _stringify([S]) != '[null]' || _stringify({ a: S }) != '{}' || _stringify(Object(S)) != '{}'; +})), 'JSON', { + stringify: function stringify(it) { + if (it === undefined || isSymbol(it)) return; // IE8 returns string on undefined + var args = [it]; + var i = 1; + var replacer, $replacer; + while (arguments.length > i) args.push(arguments[i++]); + replacer = args[1]; + if (typeof replacer == 'function') $replacer = replacer; + if ($replacer || !isArray(replacer)) replacer = function (key, value) { + if ($replacer) value = $replacer.call(this, key, value); + if (!isSymbol(value)) return value; + }; + args[1] = replacer; + return _stringify.apply($JSON, args); + } +}); + +// 19.4.3.4 Symbol.prototype[@@toPrimitive](hint) +$Symbol[PROTOTYPE][TO_PRIMITIVE] || __webpack_require__(16)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf); +// 19.4.3.5 Symbol.prototype[@@toStringTag] +setToStringTag($Symbol, 'Symbol'); +// 20.2.1.9 Math[@@toStringTag] +setToStringTag(Math, 'Math', true); +// 24.3.3 JSON[@@toStringTag] +setToStringTag(global.JSON, 'JSON', true); + + +/***/ }), +/* 221 */ +/***/ (function(module, exports, __webpack_require__) { + +var global = __webpack_require__(6); +var core = __webpack_require__(41); +var LIBRARY = __webpack_require__(42); +var wksExt = __webpack_require__(132); +var defineProperty = __webpack_require__(10).f; +module.exports = function (name) { + var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {}); + if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, { value: wksExt.f(name) }); +}; + + +/***/ }), +/* 222 */ +/***/ (function(module, exports, __webpack_require__) { + +// all enumerable object keys, includes symbols +var getKeys = __webpack_require__(37); +var gOPS = __webpack_require__(72); +var pIE = __webpack_require__(58); +module.exports = function (it) { + var result = getKeys(it); + var getSymbols = gOPS.f; + if (getSymbols) { + var symbols = getSymbols(it); + var isEnum = pIE.f; + var i = 0; + var key; + while (symbols.length > i) if (isEnum.call(it, key = symbols[i++])) result.push(key); + } return result; +}; + + +/***/ }), +/* 223 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.5 Object.freeze(O) +var isObject = __webpack_require__(5); +var meta = __webpack_require__(31).onFreeze; + +__webpack_require__(21)('freeze', function ($freeze) { + return function freeze(it) { + return $freeze && isObject(it) ? $freeze(meta(it)) : it; + }; +}); + + +/***/ }), +/* 224 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.17 Object.seal(O) +var isObject = __webpack_require__(5); +var meta = __webpack_require__(31).onFreeze; + +__webpack_require__(21)('seal', function ($seal) { + return function seal(it) { + return $seal && isObject(it) ? $seal(meta(it)) : it; + }; +}); + + +/***/ }), +/* 225 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.15 Object.preventExtensions(O) +var isObject = __webpack_require__(5); +var meta = __webpack_require__(31).onFreeze; + +__webpack_require__(21)('preventExtensions', function ($preventExtensions) { + return function preventExtensions(it) { + return $preventExtensions && isObject(it) ? $preventExtensions(meta(it)) : it; + }; +}); + + +/***/ }), +/* 226 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.12 Object.isFrozen(O) +var isObject = __webpack_require__(5); + +__webpack_require__(21)('isFrozen', function ($isFrozen) { + return function isFrozen(it) { + return isObject(it) ? $isFrozen ? $isFrozen(it) : false : true; + }; +}); + + +/***/ }), +/* 227 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.13 Object.isSealed(O) +var isObject = __webpack_require__(5); + +__webpack_require__(21)('isSealed', function ($isSealed) { + return function isSealed(it) { + return isObject(it) ? $isSealed ? $isSealed(it) : false : true; + }; +}); + + +/***/ }), +/* 228 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.11 Object.isExtensible(O) +var isObject = __webpack_require__(5); + +__webpack_require__(21)('isExtensible', function ($isExtensible) { + return function isExtensible(it) { + return isObject(it) ? $isExtensible ? $isExtensible(it) : true : false; + }; +}); + + +/***/ }), +/* 229 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) +var toIObject = __webpack_require__(20); +var $getOwnPropertyDescriptor = __webpack_require__(26).f; + +__webpack_require__(21)('getOwnPropertyDescriptor', function () { + return function getOwnPropertyDescriptor(it, key) { + return $getOwnPropertyDescriptor(toIObject(it), key); + }; +}); + + +/***/ }), +/* 230 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.9 Object.getPrototypeOf(O) +var toObject = __webpack_require__(24); +var $getPrototypeOf = __webpack_require__(49); + +__webpack_require__(21)('getPrototypeOf', function () { + return function getPrototypeOf(it) { + return $getPrototypeOf(toObject(it)); + }; +}); + + +/***/ }), +/* 231 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.14 Object.keys(O) +var toObject = __webpack_require__(24); +var $keys = __webpack_require__(37); + +__webpack_require__(21)('keys', function () { + return function keys(it) { + return $keys(toObject(it)); + }; +}); + + +/***/ }), +/* 232 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.2.7 Object.getOwnPropertyNames(O) +__webpack_require__(21)('getOwnPropertyNames', function () { + return __webpack_require__(133).f; +}); + + +/***/ }), +/* 233 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.3.1 Object.assign(target, source) +var $export = __webpack_require__(0); + +$export($export.S + $export.F, 'Object', { assign: __webpack_require__(127) }); + + +/***/ }), +/* 234 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.3.10 Object.is(value1, value2) +var $export = __webpack_require__(0); +$export($export.S, 'Object', { is: __webpack_require__(235) }); + + +/***/ }), +/* 235 */ +/***/ (function(module, exports) { + +// 7.2.9 SameValue(x, y) +module.exports = Object.is || function is(x, y) { + // eslint-disable-next-line no-self-compare + return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y; +}; + + +/***/ }), +/* 236 */ +/***/ (function(module, exports, __webpack_require__) { + +// 19.1.3.19 Object.setPrototypeOf(O, proto) +var $export = __webpack_require__(0); +$export($export.S, 'Object', { setPrototypeOf: __webpack_require__(97).set }); + + +/***/ }), +/* 237 */ +/***/ (function(module, exports, __webpack_require__) { + +var dP = __webpack_require__(10).f; +var FProto = Function.prototype; +var nameRE = /^\s*function ([^ (]*)/; +var NAME = 'name'; + +// 19.2.4.2 name +NAME in FProto || __webpack_require__(13) && dP(FProto, NAME, { + configurable: true, + get: function () { + try { + return ('' + this).match(nameRE)[1]; + } catch (e) { + return ''; + } + } +}); + + +/***/ }), +/* 238 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(0); +var toIObject = __webpack_require__(20); +var toLength = __webpack_require__(12); + +$export($export.S, 'String', { + // 21.1.2.4 String.raw(callSite, ...substitutions) + raw: function raw(callSite) { + var tpl = toIObject(callSite.raw); + var len = toLength(tpl.length); + var aLen = arguments.length; + var res = []; + var i = 0; + while (len > i) { + res.push(String(tpl[i++])); + if (i < aLen) res.push(String(arguments[i])); + } return res.join(''); + } +}); + + +/***/ }), +/* 239 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(0); +var toAbsoluteIndex = __webpack_require__(46); +var fromCharCode = String.fromCharCode; +var $fromCodePoint = String.fromCodePoint; + +// length should be 1, old FF problem +$export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', { + // 21.1.2.2 String.fromCodePoint(...codePoints) + fromCodePoint: function fromCodePoint(x) { // eslint-disable-line no-unused-vars + var res = []; + var aLen = arguments.length; + var i = 0; + var code; + while (aLen > i) { + code = +arguments[i++]; + if (toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point'); + res.push(code < 0x10000 + ? fromCharCode(code) + : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00) + ); + } return res.join(''); + } +}); + + +/***/ }), +/* 240 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var $export = __webpack_require__(0); +var $at = __webpack_require__(241)(false); +$export($export.P, 'String', { + // 21.1.3.3 String.prototype.codePointAt(pos) + codePointAt: function codePointAt(pos) { + return $at(this, pos); + } +}); + + +/***/ }), +/* 241 */ +/***/ (function(module, exports, __webpack_require__) { + +var toInteger = __webpack_require__(36); +var defined = __webpack_require__(30); +// true -> String#at +// false -> String#codePointAt +module.exports = function (TO_STRING) { + return function (that, pos) { + var s = String(defined(that)); + var i = toInteger(pos); + var l = s.length; + var a, b; + if (i < 0 || i >= l) return TO_STRING ? '' : undefined; + a = s.charCodeAt(i); + return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff + ? TO_STRING ? s.charAt(i) : a + : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; + }; +}; + + +/***/ }), +/* 242 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(0); + +$export($export.P, 'String', { + // 21.1.3.13 String.prototype.repeat(count) + repeat: __webpack_require__(134) +}); + + +/***/ }), +/* 243 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// 21.1.3.18 String.prototype.startsWith(searchString [, position ]) + +var $export = __webpack_require__(0); +var toLength = __webpack_require__(12); +var context = __webpack_require__(99); +var STARTS_WITH = 'startsWith'; +var $startsWith = ''[STARTS_WITH]; + +$export($export.P + $export.F * __webpack_require__(100)(STARTS_WITH), 'String', { + startsWith: function startsWith(searchString /* , position = 0 */) { + var that = context(this, searchString, STARTS_WITH); + var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length)); + var search = String(searchString); + return $startsWith + ? $startsWith.call(that, search, index) + : that.slice(index, index + search.length) === search; + } +}); + + +/***/ }), +/* 244 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// 21.1.3.6 String.prototype.endsWith(searchString [, endPosition]) + +var $export = __webpack_require__(0); +var toLength = __webpack_require__(12); +var context = __webpack_require__(99); +var ENDS_WITH = 'endsWith'; +var $endsWith = ''[ENDS_WITH]; + +$export($export.P + $export.F * __webpack_require__(100)(ENDS_WITH), 'String', { + endsWith: function endsWith(searchString /* , endPosition = @length */) { + var that = context(this, searchString, ENDS_WITH); + var endPosition = arguments.length > 1 ? arguments[1] : undefined; + var len = toLength(that.length); + var end = endPosition === undefined ? len : Math.min(toLength(endPosition), len); + var search = String(searchString); + return $endsWith + ? $endsWith.call(that, search, end) + : that.slice(end - search.length, end) === search; + } +}); + + +/***/ }), +/* 245 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// 21.1.3.7 String.prototype.includes(searchString, position = 0) + +var $export = __webpack_require__(0); +var context = __webpack_require__(99); +var INCLUDES = 'includes'; + +$export($export.P + $export.F * __webpack_require__(100)(INCLUDES), 'String', { + includes: function includes(searchString /* , position = 0 */) { + return !!~context(this, searchString, INCLUDES) + .indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined); + } +}); + + +/***/ }), +/* 246 */ +/***/ (function(module, exports, __webpack_require__) { + +// 21.2.5.3 get RegExp.prototype.flags() +if (__webpack_require__(13) && /./g.flags != 'g') __webpack_require__(10).f(RegExp.prototype, 'flags', { + configurable: true, + get: __webpack_require__(247) +}); + + +/***/ }), +/* 247 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// 21.2.5.3 get RegExp.prototype.flags +var anObject = __webpack_require__(7); +module.exports = function () { + var that = anObject(this); + var result = ''; + if (that.global) result += 'g'; + if (that.ignoreCase) result += 'i'; + if (that.multiline) result += 'm'; + if (that.unicode) result += 'u'; + if (that.sticky) result += 'y'; + return result; +}; + + +/***/ }), +/* 248 */ +/***/ (function(module, exports, __webpack_require__) { + +// @@match logic +__webpack_require__(73)('match', 1, function (defined, MATCH, $match) { + // 21.1.3.11 String.prototype.match(regexp) + return [function match(regexp) { + 'use strict'; + var O = defined(this); + var fn = regexp == undefined ? undefined : regexp[MATCH]; + return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[MATCH](String(O)); + }, $match]; +}); + + +/***/ }), +/* 249 */ +/***/ (function(module, exports, __webpack_require__) { + +// @@replace logic +__webpack_require__(73)('replace', 2, function (defined, REPLACE, $replace) { + // 21.1.3.14 String.prototype.replace(searchValue, replaceValue) + return [function replace(searchValue, replaceValue) { + 'use strict'; + var O = defined(this); + var fn = searchValue == undefined ? undefined : searchValue[REPLACE]; + return fn !== undefined + ? fn.call(searchValue, O, replaceValue) + : $replace.call(String(O), searchValue, replaceValue); + }, $replace]; +}); + + +/***/ }), +/* 250 */ +/***/ (function(module, exports, __webpack_require__) { + +// @@split logic +__webpack_require__(73)('split', 2, function (defined, SPLIT, $split) { + 'use strict'; + var isRegExp = __webpack_require__(135); + var _split = $split; + var $push = [].push; + var $SPLIT = 'split'; + var LENGTH = 'length'; + var LAST_INDEX = 'lastIndex'; + if ( + 'abbc'[$SPLIT](/(b)*/)[1] == 'c' || + 'test'[$SPLIT](/(?:)/, -1)[LENGTH] != 4 || + 'ab'[$SPLIT](/(?:ab)*/)[LENGTH] != 2 || + '.'[$SPLIT](/(.?)(.?)/)[LENGTH] != 4 || + '.'[$SPLIT](/()()/)[LENGTH] > 1 || + ''[$SPLIT](/.?/)[LENGTH] + ) { + var NPCG = /()??/.exec('')[1] === undefined; // nonparticipating capturing group + // based on es5-shim implementation, need to rework it + $split = function (separator, limit) { + var string = String(this); + if (separator === undefined && limit === 0) return []; + // If `separator` is not a regex, use native split + if (!isRegExp(separator)) return _split.call(string, separator, limit); + var output = []; + var flags = (separator.ignoreCase ? 'i' : '') + + (separator.multiline ? 'm' : '') + + (separator.unicode ? 'u' : '') + + (separator.sticky ? 'y' : ''); + var lastLastIndex = 0; + var splitLimit = limit === undefined ? 4294967295 : limit >>> 0; + // Make `global` and avoid `lastIndex` issues by working with a copy + var separatorCopy = new RegExp(separator.source, flags + 'g'); + var separator2, match, lastIndex, lastLength, i; + // Doesn't need flags gy, but they don't hurt + if (!NPCG) separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags); + while (match = separatorCopy.exec(string)) { + // `separatorCopy.lastIndex` is not reliable cross-browser + lastIndex = match.index + match[0][LENGTH]; + if (lastIndex > lastLastIndex) { + output.push(string.slice(lastLastIndex, match.index)); + // Fix browsers whose `exec` methods don't consistently return `undefined` for NPCG + // eslint-disable-next-line no-loop-func + if (!NPCG && match[LENGTH] > 1) match[0].replace(separator2, function () { + for (i = 1; i < arguments[LENGTH] - 2; i++) if (arguments[i] === undefined) match[i] = undefined; + }); + if (match[LENGTH] > 1 && match.index < string[LENGTH]) $push.apply(output, match.slice(1)); + lastLength = match[0][LENGTH]; + lastLastIndex = lastIndex; + if (output[LENGTH] >= splitLimit) break; + } + if (separatorCopy[LAST_INDEX] === match.index) separatorCopy[LAST_INDEX]++; // Avoid an infinite loop + } + if (lastLastIndex === string[LENGTH]) { + if (lastLength || !separatorCopy.test('')) output.push(''); + } else output.push(string.slice(lastLastIndex)); + return output[LENGTH] > splitLimit ? output.slice(0, splitLimit) : output; + }; + // Chakra, V8 + } else if ('0'[$SPLIT](undefined, 0)[LENGTH]) { + $split = function (separator, limit) { + return separator === undefined && limit === 0 ? [] : _split.call(this, separator, limit); + }; + } + // 21.1.3.17 String.prototype.split(separator, limit) + return [function split(separator, limit) { + var O = defined(this); + var fn = separator == undefined ? undefined : separator[SPLIT]; + return fn !== undefined ? fn.call(separator, O, limit) : $split.call(String(O), separator, limit); + }, $split]; +}); + + +/***/ }), +/* 251 */ +/***/ (function(module, exports, __webpack_require__) { + +// @@search logic +__webpack_require__(73)('search', 1, function (defined, SEARCH, $search) { + // 21.1.3.15 String.prototype.search(regexp) + return [function search(regexp) { + 'use strict'; + var O = defined(this); + var fn = regexp == undefined ? undefined : regexp[SEARCH]; + return fn !== undefined ? fn.call(regexp, O) : new RegExp(regexp)[SEARCH](String(O)); + }, $search]; +}); + + +/***/ }), +/* 252 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var ctx = __webpack_require__(23); +var $export = __webpack_require__(0); +var toObject = __webpack_require__(24); +var call = __webpack_require__(126); +var isArrayIter = __webpack_require__(94); +var toLength = __webpack_require__(12); +var createProperty = __webpack_require__(101); +var getIterFn = __webpack_require__(95); + +$export($export.S + $export.F * !__webpack_require__(69)(function (iter) { Array.from(iter); }), 'Array', { + // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) + from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) { + var O = toObject(arrayLike); + var C = typeof this == 'function' ? this : Array; + var aLen = arguments.length; + var mapfn = aLen > 1 ? arguments[1] : undefined; + var mapping = mapfn !== undefined; + var index = 0; + var iterFn = getIterFn(O); + var length, result, step, iterator; + if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); + // if object isn't iterable or it's array with default iterator - use simple case + if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) { + for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) { + createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value); + } + } else { + length = toLength(O.length); + for (result = new C(length); length > index; index++) { + createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]); + } + } + result.length = index; + return result; + } +}); + + +/***/ }), +/* 253 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var $export = __webpack_require__(0); +var createProperty = __webpack_require__(101); + +// WebKit Array.of isn't generic +$export($export.S + $export.F * __webpack_require__(8)(function () { + function F() { /* empty */ } + return !(Array.of.call(F) instanceof F); +}), 'Array', { + // 22.1.2.3 Array.of( ...items) + of: function of(/* ...args */) { + var index = 0; + var aLen = arguments.length; + var result = new (typeof this == 'function' ? this : Array)(aLen); + while (aLen > index) createProperty(result, index, arguments[index++]); + result.length = aLen; + return result; + } +}); + + +/***/ }), +/* 254 */ +/***/ (function(module, exports, __webpack_require__) { + +// 22.1.3.3 Array.prototype.copyWithin(target, start, end = this.length) +var $export = __webpack_require__(0); + +$export($export.P, 'Array', { copyWithin: __webpack_require__(124) }); + +__webpack_require__(50)('copyWithin'); + + +/***/ }), +/* 255 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// 22.1.3.8 Array.prototype.find(predicate, thisArg = undefined) +var $export = __webpack_require__(0); +var $find = __webpack_require__(57)(5); +var KEY = 'find'; +var forced = true; +// Shouldn't skip holes +if (KEY in []) Array(1)[KEY](function () { forced = false; }); +$export($export.P + $export.F * forced, 'Array', { + find: function find(callbackfn /* , that = undefined */) { + return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } +}); +__webpack_require__(50)(KEY); + + +/***/ }), +/* 256 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// 22.1.3.9 Array.prototype.findIndex(predicate, thisArg = undefined) +var $export = __webpack_require__(0); +var $find = __webpack_require__(57)(6); +var KEY = 'findIndex'; +var forced = true; +// Shouldn't skip holes +if (KEY in []) Array(1)[KEY](function () { forced = false; }); +$export($export.P + $export.F * forced, 'Array', { + findIndex: function findIndex(callbackfn /* , that = undefined */) { + return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + } +}); +__webpack_require__(50)(KEY); + + +/***/ }), +/* 257 */ +/***/ (function(module, exports, __webpack_require__) { + +// 22.1.3.6 Array.prototype.fill(value, start = 0, end = this.length) +var $export = __webpack_require__(0); + +$export($export.P, 'Array', { fill: __webpack_require__(91) }); + +__webpack_require__(50)('fill'); + + +/***/ }), +/* 258 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.2 Number.isFinite(number) +var $export = __webpack_require__(0); +var _isFinite = __webpack_require__(6).isFinite; + +$export($export.S, 'Number', { + isFinite: function isFinite(it) { + return typeof it == 'number' && _isFinite(it); + } +}); + + +/***/ }), +/* 259 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.3 Number.isInteger(number) +var $export = __webpack_require__(0); + +$export($export.S, 'Number', { isInteger: __webpack_require__(136) }); + + +/***/ }), +/* 260 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.5 Number.isSafeInteger(number) +var $export = __webpack_require__(0); +var isInteger = __webpack_require__(136); +var abs = Math.abs; + +$export($export.S, 'Number', { + isSafeInteger: function isSafeInteger(number) { + return isInteger(number) && abs(number) <= 0x1fffffffffffff; + } +}); + + +/***/ }), +/* 261 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.4 Number.isNaN(number) +var $export = __webpack_require__(0); + +$export($export.S, 'Number', { + isNaN: function isNaN(number) { + // eslint-disable-next-line no-self-compare + return number != number; + } +}); + + +/***/ }), +/* 262 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.1 Number.EPSILON +var $export = __webpack_require__(0); + +$export($export.S, 'Number', { EPSILON: Math.pow(2, -52) }); + + +/***/ }), +/* 263 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.10 Number.MIN_SAFE_INTEGER +var $export = __webpack_require__(0); + +$export($export.S, 'Number', { MIN_SAFE_INTEGER: -0x1fffffffffffff }); + + +/***/ }), +/* 264 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.1.2.6 Number.MAX_SAFE_INTEGER +var $export = __webpack_require__(0); + +$export($export.S, 'Number', { MAX_SAFE_INTEGER: 0x1fffffffffffff }); + + +/***/ }), +/* 265 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(0); +var $parseFloat = __webpack_require__(266); +// 20.1.2.12 Number.parseFloat(string) +$export($export.S + $export.F * (Number.parseFloat != $parseFloat), 'Number', { parseFloat: $parseFloat }); + + +/***/ }), +/* 266 */ +/***/ (function(module, exports, __webpack_require__) { + +var $parseFloat = __webpack_require__(6).parseFloat; +var $trim = __webpack_require__(137).trim; + +module.exports = 1 / $parseFloat(__webpack_require__(102) + '-0') !== -Infinity ? function parseFloat(str) { + var string = $trim(String(str), 3); + var result = $parseFloat(string); + return result === 0 && string.charAt(0) == '-' ? -0 : result; +} : $parseFloat; + + +/***/ }), +/* 267 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(0); +var $parseInt = __webpack_require__(268); +// 20.1.2.13 Number.parseInt(string, radix) +$export($export.S + $export.F * (Number.parseInt != $parseInt), 'Number', { parseInt: $parseInt }); + + +/***/ }), +/* 268 */ +/***/ (function(module, exports, __webpack_require__) { + +var $parseInt = __webpack_require__(6).parseInt; +var $trim = __webpack_require__(137).trim; +var ws = __webpack_require__(102); +var hex = /^[-+]?0[xX]/; + +module.exports = $parseInt(ws + '08') !== 8 || $parseInt(ws + '0x16') !== 22 ? function parseInt(str, radix) { + var string = $trim(String(str), 3); + return $parseInt(string, (radix >>> 0) || (hex.test(string) ? 16 : 10)); +} : $parseInt; + + +/***/ }), +/* 269 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.3 Math.acosh(x) +var $export = __webpack_require__(0); +var log1p = __webpack_require__(138); +var sqrt = Math.sqrt; +var $acosh = Math.acosh; + +$export($export.S + $export.F * !($acosh + // V8 bug: https://code.google.com/p/v8/issues/detail?id=3509 + && Math.floor($acosh(Number.MAX_VALUE)) == 710 + // Tor Browser bug: Math.acosh(Infinity) -> NaN + && $acosh(Infinity) == Infinity +), 'Math', { + acosh: function acosh(x) { + return (x = +x) < 1 ? NaN : x > 94906265.62425156 + ? Math.log(x) + Math.LN2 + : log1p(x - 1 + sqrt(x - 1) * sqrt(x + 1)); + } +}); + + +/***/ }), +/* 270 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.5 Math.asinh(x) +var $export = __webpack_require__(0); +var $asinh = Math.asinh; + +function asinh(x) { + return !isFinite(x = +x) || x == 0 ? x : x < 0 ? -asinh(-x) : Math.log(x + Math.sqrt(x * x + 1)); +} + +// Tor Browser bug: Math.asinh(0) -> -0 +$export($export.S + $export.F * !($asinh && 1 / $asinh(0) > 0), 'Math', { asinh: asinh }); + + +/***/ }), +/* 271 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.7 Math.atanh(x) +var $export = __webpack_require__(0); +var $atanh = Math.atanh; + +// Tor Browser bug: Math.atanh(-0) -> 0 +$export($export.S + $export.F * !($atanh && 1 / $atanh(-0) < 0), 'Math', { + atanh: function atanh(x) { + return (x = +x) == 0 ? x : Math.log((1 + x) / (1 - x)) / 2; + } +}); + + +/***/ }), +/* 272 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.9 Math.cbrt(x) +var $export = __webpack_require__(0); +var sign = __webpack_require__(103); + +$export($export.S, 'Math', { + cbrt: function cbrt(x) { + return sign(x = +x) * Math.pow(Math.abs(x), 1 / 3); + } +}); + + +/***/ }), +/* 273 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.11 Math.clz32(x) +var $export = __webpack_require__(0); + +$export($export.S, 'Math', { + clz32: function clz32(x) { + return (x >>>= 0) ? 31 - Math.floor(Math.log(x + 0.5) * Math.LOG2E) : 32; + } +}); + + +/***/ }), +/* 274 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.12 Math.cosh(x) +var $export = __webpack_require__(0); +var exp = Math.exp; + +$export($export.S, 'Math', { + cosh: function cosh(x) { + return (exp(x = +x) + exp(-x)) / 2; + } +}); + + +/***/ }), +/* 275 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.14 Math.expm1(x) +var $export = __webpack_require__(0); +var $expm1 = __webpack_require__(104); + +$export($export.S + $export.F * ($expm1 != Math.expm1), 'Math', { expm1: $expm1 }); + + +/***/ }), +/* 276 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.16 Math.fround(x) +var $export = __webpack_require__(0); + +$export($export.S, 'Math', { fround: __webpack_require__(277) }); + + +/***/ }), +/* 277 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.16 Math.fround(x) +var sign = __webpack_require__(103); +var pow = Math.pow; +var EPSILON = pow(2, -52); +var EPSILON32 = pow(2, -23); +var MAX32 = pow(2, 127) * (2 - EPSILON32); +var MIN32 = pow(2, -126); + +var roundTiesToEven = function (n) { + return n + 1 / EPSILON - 1 / EPSILON; +}; + +module.exports = Math.fround || function fround(x) { + var $abs = Math.abs(x); + var $sign = sign(x); + var a, result; + if ($abs < MIN32) return $sign * roundTiesToEven($abs / MIN32 / EPSILON32) * MIN32 * EPSILON32; + a = (1 + EPSILON32 / EPSILON) * $abs; + result = a - (a - $abs); + // eslint-disable-next-line no-self-compare + if (result > MAX32 || result != result) return $sign * Infinity; + return $sign * result; +}; + + +/***/ }), +/* 278 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.17 Math.hypot([value1[, value2[, … ]]]) +var $export = __webpack_require__(0); +var abs = Math.abs; + +$export($export.S, 'Math', { + hypot: function hypot(value1, value2) { // eslint-disable-line no-unused-vars + var sum = 0; + var i = 0; + var aLen = arguments.length; + var larg = 0; + var arg, div; + while (i < aLen) { + arg = abs(arguments[i++]); + if (larg < arg) { + div = larg / arg; + sum = sum * div * div + 1; + larg = arg; + } else if (arg > 0) { + div = arg / larg; + sum += div * div; + } else sum += arg; + } + return larg === Infinity ? Infinity : larg * Math.sqrt(sum); + } +}); + + +/***/ }), +/* 279 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.18 Math.imul(x, y) +var $export = __webpack_require__(0); +var $imul = Math.imul; + +// some WebKit versions fails with big numbers, some has wrong arity +$export($export.S + $export.F * __webpack_require__(8)(function () { + return $imul(0xffffffff, 5) != -5 || $imul.length != 2; +}), 'Math', { + imul: function imul(x, y) { + var UINT16 = 0xffff; + var xn = +x; + var yn = +y; + var xl = UINT16 & xn; + var yl = UINT16 & yn; + return 0 | xl * yl + ((UINT16 & xn >>> 16) * yl + xl * (UINT16 & yn >>> 16) << 16 >>> 0); + } +}); + + +/***/ }), +/* 280 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.20 Math.log1p(x) +var $export = __webpack_require__(0); + +$export($export.S, 'Math', { log1p: __webpack_require__(138) }); + + +/***/ }), +/* 281 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.21 Math.log10(x) +var $export = __webpack_require__(0); + +$export($export.S, 'Math', { + log10: function log10(x) { + return Math.log(x) * Math.LOG10E; + } +}); + + +/***/ }), +/* 282 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.22 Math.log2(x) +var $export = __webpack_require__(0); + +$export($export.S, 'Math', { + log2: function log2(x) { + return Math.log(x) / Math.LN2; + } +}); + + +/***/ }), +/* 283 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.28 Math.sign(x) +var $export = __webpack_require__(0); + +$export($export.S, 'Math', { sign: __webpack_require__(103) }); + + +/***/ }), +/* 284 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.30 Math.sinh(x) +var $export = __webpack_require__(0); +var expm1 = __webpack_require__(104); +var exp = Math.exp; + +// V8 near Chromium 38 has a problem with very small numbers +$export($export.S + $export.F * __webpack_require__(8)(function () { + return !Math.sinh(-2e-17) != -2e-17; +}), 'Math', { + sinh: function sinh(x) { + return Math.abs(x = +x) < 1 + ? (expm1(x) - expm1(-x)) / 2 + : (exp(x - 1) - exp(-x - 1)) * (Math.E / 2); + } +}); + + +/***/ }), +/* 285 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.33 Math.tanh(x) +var $export = __webpack_require__(0); +var expm1 = __webpack_require__(104); +var exp = Math.exp; + +$export($export.S, 'Math', { + tanh: function tanh(x) { + var a = expm1(x = +x); + var b = expm1(-x); + return a == Infinity ? 1 : b == Infinity ? -1 : (a - b) / (exp(x) + exp(-x)); + } +}); + + +/***/ }), +/* 286 */ +/***/ (function(module, exports, __webpack_require__) { + +// 20.2.2.34 Math.trunc(x) +var $export = __webpack_require__(0); + +$export($export.S, 'Math', { + trunc: function trunc(it) { + return (it > 0 ? Math.floor : Math.ceil)(it); + } +}); + + +/***/ }), +/* 287 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// https://github.com/tc39/Array.prototype.includes +var $export = __webpack_require__(0); +var $includes = __webpack_require__(87)(true); + +$export($export.P, 'Array', { + includes: function includes(el /* , fromIndex = 0 */) { + return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined); + } +}); + +__webpack_require__(50)('includes'); + + +/***/ }), +/* 288 */ +/***/ (function(module, exports, __webpack_require__) { + +// https://github.com/tc39/proposal-object-values-entries +var $export = __webpack_require__(0); +var $values = __webpack_require__(139)(false); + +$export($export.S, 'Object', { + values: function values(it) { + return $values(it); + } +}); + + +/***/ }), +/* 289 */ +/***/ (function(module, exports, __webpack_require__) { + +// https://github.com/tc39/proposal-object-values-entries +var $export = __webpack_require__(0); +var $entries = __webpack_require__(139)(true); + +$export($export.S, 'Object', { + entries: function entries(it) { + return $entries(it); + } +}); + + +/***/ }), +/* 290 */ +/***/ (function(module, exports, __webpack_require__) { + +// https://github.com/tc39/proposal-object-getownpropertydescriptors +var $export = __webpack_require__(0); +var ownKeys = __webpack_require__(130); +var toIObject = __webpack_require__(20); +var gOPD = __webpack_require__(26); +var createProperty = __webpack_require__(101); + +$export($export.S, 'Object', { + getOwnPropertyDescriptors: function getOwnPropertyDescriptors(object) { + var O = toIObject(object); + var getDesc = gOPD.f; + var keys = ownKeys(O); + var result = {}; + var i = 0; + var key, desc; + while (keys.length > i) { + desc = getDesc(O, key = keys[i++]); + if (desc !== undefined) createProperty(result, key, desc); + } + return result; + } +}); + + +/***/ }), +/* 291 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// https://github.com/tc39/proposal-string-pad-start-end +var $export = __webpack_require__(0); +var $pad = __webpack_require__(140); + +$export($export.P, 'String', { + padStart: function padStart(maxLength /* , fillString = ' ' */) { + return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, true); + } +}); + + +/***/ }), +/* 292 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +// https://github.com/tc39/proposal-string-pad-start-end +var $export = __webpack_require__(0); +var $pad = __webpack_require__(140); + +$export($export.P, 'String', { + padEnd: function padEnd(maxLength /* , fillString = ' ' */) { + return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, false); + } +}); + + +/***/ }), +/* 293 */ +/***/ (function(module, exports, __webpack_require__) { + +// ie9- setTimeout & setInterval additional parameters fix +var global = __webpack_require__(6); +var $export = __webpack_require__(0); +var navigator = global.navigator; +var slice = [].slice; +var MSIE = !!navigator && /MSIE .\./.test(navigator.userAgent); // <- dirty ie9- check +var wrap = function (set) { + return function (fn, time /* , ...args */) { + var boundArgs = arguments.length > 2; + var args = boundArgs ? slice.call(arguments, 2) : false; + return set(boundArgs ? function () { + // eslint-disable-next-line no-new-func + (typeof fn == 'function' ? fn : Function(fn)).apply(this, args); + } : fn, time); + }; +}; +$export($export.G + $export.B + $export.F * MSIE, { + setTimeout: wrap(global.setTimeout), + setInterval: wrap(global.setInterval) +}); + + +/***/ }), +/* 294 */ +/***/ (function(module, exports, __webpack_require__) { + +var $export = __webpack_require__(0); +var $task = __webpack_require__(98); +$export($export.G + $export.B, { + setImmediate: $task.set, + clearImmediate: $task.clear +}); + + +/***/ }), +/* 295 */ +/***/ (function(module, exports, __webpack_require__) { + +var $iterators = __webpack_require__(96); +var getKeys = __webpack_require__(37); +var redefine = __webpack_require__(29); +var global = __webpack_require__(6); +var hide = __webpack_require__(16); +var Iterators = __webpack_require__(48); +var wks = __webpack_require__(9); +var ITERATOR = wks('iterator'); +var TO_STRING_TAG = wks('toStringTag'); +var ArrayValues = Iterators.Array; + +var DOMIterables = { + CSSRuleList: true, // TODO: Not spec compliant, should be false. + CSSStyleDeclaration: false, + CSSValueList: false, + ClientRectList: false, + DOMRectList: false, + DOMStringList: false, + DOMTokenList: true, + DataTransferItemList: false, + FileList: false, + HTMLAllCollection: false, + HTMLCollection: false, + HTMLFormElement: false, + HTMLSelectElement: false, + MediaList: true, // TODO: Not spec compliant, should be false. + MimeTypeArray: false, + NamedNodeMap: false, + NodeList: true, + PaintRequestList: false, + Plugin: false, + PluginArray: false, + SVGLengthList: false, + SVGNumberList: false, + SVGPathSegList: false, + SVGPointList: false, + SVGStringList: false, + SVGTransformList: false, + SourceBufferList: false, + StyleSheetList: true, // TODO: Not spec compliant, should be false. + TextTrackCueList: false, + TextTrackList: false, + TouchList: false +}; + +for (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) { + var NAME = collections[i]; + var explicit = DOMIterables[NAME]; + var Collection = global[NAME]; + var proto = Collection && Collection.prototype; + var key; + if (proto) { + if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues); + if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME); + Iterators[NAME] = ArrayValues; + if (explicit) for (key in $iterators) if (!proto[key]) redefine(proto, key, $iterators[key], true); + } +} + + +/***/ }), +/* 296 */ +/***/ (function(module, exports) { + +/** + * Copyright (c) 2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * https://raw.github.com/facebook/regenerator/master/LICENSE file. An + * additional grant of patent rights can be found in the PATENTS file in + * the same directory. + */ + +!(function(global) { + "use strict"; + + var Op = Object.prototype; + var hasOwn = Op.hasOwnProperty; + var undefined; // More compressible than void 0. + var $Symbol = typeof Symbol === "function" ? Symbol : {}; + var iteratorSymbol = $Symbol.iterator || "@@iterator"; + var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; + var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; + + var inModule = typeof module === "object"; + var runtime = global.regeneratorRuntime; + if (runtime) { + if (inModule) { + // If regeneratorRuntime is defined globally and we're in a module, + // make the exports object identical to regeneratorRuntime. + module.exports = runtime; + } + // Don't bother evaluating the rest of this file if the runtime was + // already defined globally. + return; + } + + // Define the runtime globally (as expected by generated code) as either + // module.exports (if we're in a module) or a new, empty object. + runtime = global.regeneratorRuntime = inModule ? module.exports : {}; + + function wrap(innerFn, outerFn, self, tryLocsList) { + // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator. + var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; + var generator = Object.create(protoGenerator.prototype); + var context = new Context(tryLocsList || []); + + // The ._invoke method unifies the implementations of the .next, + // .throw, and .return methods. + generator._invoke = makeInvokeMethod(innerFn, self, context); + + return generator; + } + runtime.wrap = wrap; + + // Try/catch helper to minimize deoptimizations. Returns a completion + // record like context.tryEntries[i].completion. This interface could + // have been (and was previously) designed to take a closure to be + // invoked without arguments, but in all the cases we care about we + // already have an existing method we want to call, so there's no need + // to create a new function object. We can even get away with assuming + // the method takes exactly one argument, since that happens to be true + // in every case, so we don't have to touch the arguments object. The + // only additional allocation required is the completion record, which + // has a stable shape and so hopefully should be cheap to allocate. + function tryCatch(fn, obj, arg) { + try { + return { type: "normal", arg: fn.call(obj, arg) }; + } catch (err) { + return { type: "throw", arg: err }; + } + } + + var GenStateSuspendedStart = "suspendedStart"; + var GenStateSuspendedYield = "suspendedYield"; + var GenStateExecuting = "executing"; + var GenStateCompleted = "completed"; + + // Returning this object from the innerFn has the same effect as + // breaking out of the dispatch switch statement. + var ContinueSentinel = {}; + + // Dummy constructor functions that we use as the .constructor and + // .constructor.prototype properties for functions that return Generator + // objects. For full spec compliance, you may wish to configure your + // minifier not to mangle the names of these two functions. + function Generator() {} + function GeneratorFunction() {} + function GeneratorFunctionPrototype() {} + + // This is a polyfill for %IteratorPrototype% for environments that + // don't natively support it. + var IteratorPrototype = {}; + IteratorPrototype[iteratorSymbol] = function () { + return this; + }; + + var getProto = Object.getPrototypeOf; + var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); + if (NativeIteratorPrototype && + NativeIteratorPrototype !== Op && + hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) { + // This environment has a native %IteratorPrototype%; use it instead + // of the polyfill. + IteratorPrototype = NativeIteratorPrototype; + } + + var Gp = GeneratorFunctionPrototype.prototype = + Generator.prototype = Object.create(IteratorPrototype); + GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; + GeneratorFunctionPrototype.constructor = GeneratorFunction; + GeneratorFunctionPrototype[toStringTagSymbol] = + GeneratorFunction.displayName = "GeneratorFunction"; + + // Helper for defining the .next, .throw, and .return methods of the + // Iterator interface in terms of a single ._invoke method. + function defineIteratorMethods(prototype) { + ["next", "throw", "return"].forEach(function(method) { + prototype[method] = function(arg) { + return this._invoke(method, arg); + }; + }); + } + + runtime.isGeneratorFunction = function(genFun) { + var ctor = typeof genFun === "function" && genFun.constructor; + return ctor + ? ctor === GeneratorFunction || + // For the native GeneratorFunction constructor, the best we can + // do is to check its .name property. + (ctor.displayName || ctor.name) === "GeneratorFunction" + : false; + }; + + runtime.mark = function(genFun) { + if (Object.setPrototypeOf) { + Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); + } else { + genFun.__proto__ = GeneratorFunctionPrototype; + if (!(toStringTagSymbol in genFun)) { + genFun[toStringTagSymbol] = "GeneratorFunction"; + } + } + genFun.prototype = Object.create(Gp); + return genFun; + }; + + // Within the body of any async function, `await x` is transformed to + // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test + // `hasOwn.call(value, "__await")` to determine if the yielded value is + // meant to be awaited. + runtime.awrap = function(arg) { + return { __await: arg }; + }; + + function AsyncIterator(generator) { + function invoke(method, arg, resolve, reject) { + var record = tryCatch(generator[method], generator, arg); + if (record.type === "throw") { + reject(record.arg); + } else { + var result = record.arg; + var value = result.value; + if (value && + typeof value === "object" && + hasOwn.call(value, "__await")) { + return Promise.resolve(value.__await).then(function(value) { + invoke("next", value, resolve, reject); + }, function(err) { + invoke("throw", err, resolve, reject); + }); + } + + return Promise.resolve(value).then(function(unwrapped) { + // When a yielded Promise is resolved, its final value becomes + // the .value of the Promise<{value,done}> result for the + // current iteration. If the Promise is rejected, however, the + // result for this iteration will be rejected with the same + // reason. Note that rejections of yielded Promises are not + // thrown back into the generator function, as is the case + // when an awaited Promise is rejected. This difference in + // behavior between yield and await is important, because it + // allows the consumer to decide what to do with the yielded + // rejection (swallow it and continue, manually .throw it back + // into the generator, abandon iteration, whatever). With + // await, by contrast, there is no opportunity to examine the + // rejection reason outside the generator function, so the + // only option is to throw it from the await expression, and + // let the generator function handle the exception. + result.value = unwrapped; + resolve(result); + }, reject); + } + } + + var previousPromise; + + function enqueue(method, arg) { + function callInvokeWithMethodAndArg() { + return new Promise(function(resolve, reject) { + invoke(method, arg, resolve, reject); + }); + } + + return previousPromise = + // If enqueue has been called before, then we want to wait until + // all previous Promises have been resolved before calling invoke, + // so that results are always delivered in the correct order. If + // enqueue has not been called before, then it is important to + // call invoke immediately, without waiting on a callback to fire, + // so that the async generator function has the opportunity to do + // any necessary setup in a predictable way. This predictability + // is why the Promise constructor synchronously invokes its + // executor callback, and why async functions synchronously + // execute code before the first await. Since we implement simple + // async functions in terms of async generators, it is especially + // important to get this right, even though it requires care. + previousPromise ? previousPromise.then( + callInvokeWithMethodAndArg, + // Avoid propagating failures to Promises returned by later + // invocations of the iterator. + callInvokeWithMethodAndArg + ) : callInvokeWithMethodAndArg(); + } + + // Define the unified helper method that is used to implement .next, + // .throw, and .return (see defineIteratorMethods). + this._invoke = enqueue; + } + + defineIteratorMethods(AsyncIterator.prototype); + AsyncIterator.prototype[asyncIteratorSymbol] = function () { + return this; + }; + runtime.AsyncIterator = AsyncIterator; + + // Note that simple async functions are implemented on top of + // AsyncIterator objects; they just return a Promise for the value of + // the final result produced by the iterator. + runtime.async = function(innerFn, outerFn, self, tryLocsList) { + var iter = new AsyncIterator( + wrap(innerFn, outerFn, self, tryLocsList) + ); + + return runtime.isGeneratorFunction(outerFn) + ? iter // If outerFn is a generator, return the full iterator. + : iter.next().then(function(result) { + return result.done ? result.value : iter.next(); + }); + }; + + function makeInvokeMethod(innerFn, self, context) { + var state = GenStateSuspendedStart; + + return function invoke(method, arg) { + if (state === GenStateExecuting) { + throw new Error("Generator is already running"); + } + + if (state === GenStateCompleted) { + if (method === "throw") { + throw arg; + } + + // Be forgiving, per 25.3.3.3.3 of the spec: + // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume + return doneResult(); + } + + context.method = method; + context.arg = arg; + + while (true) { + var delegate = context.delegate; + if (delegate) { + var delegateResult = maybeInvokeDelegate(delegate, context); + if (delegateResult) { + if (delegateResult === ContinueSentinel) continue; + return delegateResult; + } + } + + if (context.method === "next") { + // Setting context._sent for legacy support of Babel's + // function.sent implementation. + context.sent = context._sent = context.arg; + + } else if (context.method === "throw") { + if (state === GenStateSuspendedStart) { + state = GenStateCompleted; + throw context.arg; + } + + context.dispatchException(context.arg); + + } else if (context.method === "return") { + context.abrupt("return", context.arg); + } + + state = GenStateExecuting; + + var record = tryCatch(innerFn, self, context); + if (record.type === "normal") { + // If an exception is thrown from innerFn, we leave state === + // GenStateExecuting and loop back for another invocation. + state = context.done + ? GenStateCompleted + : GenStateSuspendedYield; + + if (record.arg === ContinueSentinel) { + continue; + } + + return { + value: record.arg, + done: context.done + }; + + } else if (record.type === "throw") { + state = GenStateCompleted; + // Dispatch the exception by looping back around to the + // context.dispatchException(context.arg) call above. + context.method = "throw"; + context.arg = record.arg; + } + } + }; + } + + // Call delegate.iterator[context.method](context.arg) and handle the + // result, either by returning a { value, done } result from the + // delegate iterator, or by modifying context.method and context.arg, + // setting context.delegate to null, and returning the ContinueSentinel. + function maybeInvokeDelegate(delegate, context) { + var method = delegate.iterator[context.method]; + if (method === undefined) { + // A .throw or .return when the delegate iterator has no .throw + // method always terminates the yield* loop. + context.delegate = null; + + if (context.method === "throw") { + if (delegate.iterator.return) { + // If the delegate iterator has a return method, give it a + // chance to clean up. + context.method = "return"; + context.arg = undefined; + maybeInvokeDelegate(delegate, context); + + if (context.method === "throw") { + // If maybeInvokeDelegate(context) changed context.method from + // "return" to "throw", let that override the TypeError below. + return ContinueSentinel; + } + } + + context.method = "throw"; + context.arg = new TypeError( + "The iterator does not provide a 'throw' method"); + } + + return ContinueSentinel; + } + + var record = tryCatch(method, delegate.iterator, context.arg); + + if (record.type === "throw") { + context.method = "throw"; + context.arg = record.arg; + context.delegate = null; + return ContinueSentinel; + } + + var info = record.arg; + + if (! info) { + context.method = "throw"; + context.arg = new TypeError("iterator result is not an object"); + context.delegate = null; + return ContinueSentinel; + } + + if (info.done) { + // Assign the result of the finished delegate to the temporary + // variable specified by delegate.resultName (see delegateYield). + context[delegate.resultName] = info.value; + + // Resume execution at the desired location (see delegateYield). + context.next = delegate.nextLoc; + + // If context.method was "throw" but the delegate handled the + // exception, let the outer generator proceed normally. If + // context.method was "next", forget context.arg since it has been + // "consumed" by the delegate iterator. If context.method was + // "return", allow the original .return call to continue in the + // outer generator. + if (context.method !== "return") { + context.method = "next"; + context.arg = undefined; + } + + } else { + // Re-yield the result returned by the delegate method. + return info; + } + + // The delegate iterator is finished, so forget it and continue with + // the outer generator. + context.delegate = null; + return ContinueSentinel; + } + + // Define Generator.prototype.{next,throw,return} in terms of the + // unified ._invoke helper method. + defineIteratorMethods(Gp); + + Gp[toStringTagSymbol] = "Generator"; + + // A Generator should always return itself as the iterator object when the + // @@iterator function is called on it. Some browsers' implementations of the + // iterator prototype chain incorrectly implement this, causing the Generator + // object to not be returned from this call. This ensures that doesn't happen. + // See https://github.com/facebook/regenerator/issues/274 for more details. + Gp[iteratorSymbol] = function() { + return this; + }; + + Gp.toString = function() { + return "[object Generator]"; + }; + + function pushTryEntry(locs) { + var entry = { tryLoc: locs[0] }; + + if (1 in locs) { + entry.catchLoc = locs[1]; + } + + if (2 in locs) { + entry.finallyLoc = locs[2]; + entry.afterLoc = locs[3]; + } + + this.tryEntries.push(entry); + } + + function resetTryEntry(entry) { + var record = entry.completion || {}; + record.type = "normal"; + delete record.arg; + entry.completion = record; + } + + function Context(tryLocsList) { + // The root entry object (effectively a try statement without a catch + // or a finally block) gives us a place to store values thrown from + // locations where there is no enclosing try statement. + this.tryEntries = [{ tryLoc: "root" }]; + tryLocsList.forEach(pushTryEntry, this); + this.reset(true); + } + + runtime.keys = function(object) { + var keys = []; + for (var key in object) { + keys.push(key); + } + keys.reverse(); + + // Rather than returning an object with a next method, we keep + // things simple and return the next function itself. + return function next() { + while (keys.length) { + var key = keys.pop(); + if (key in object) { + next.value = key; + next.done = false; + return next; + } + } + + // To avoid creating an additional object, we just hang the .value + // and .done properties off the next function object itself. This + // also ensures that the minifier will not anonymize the function. + next.done = true; + return next; + }; + }; + + function values(iterable) { + if (iterable) { + var iteratorMethod = iterable[iteratorSymbol]; + if (iteratorMethod) { + return iteratorMethod.call(iterable); + } + + if (typeof iterable.next === "function") { + return iterable; + } + + if (!isNaN(iterable.length)) { + var i = -1, next = function next() { + while (++i < iterable.length) { + if (hasOwn.call(iterable, i)) { + next.value = iterable[i]; + next.done = false; + return next; + } + } + + next.value = undefined; + next.done = true; + + return next; + }; + + return next.next = next; + } + } + + // Return an iterator with no values. + return { next: doneResult }; + } + runtime.values = values; + + function doneResult() { + return { value: undefined, done: true }; + } + + Context.prototype = { + constructor: Context, + + reset: function(skipTempReset) { + this.prev = 0; + this.next = 0; + // Resetting context._sent for legacy support of Babel's + // function.sent implementation. + this.sent = this._sent = undefined; + this.done = false; + this.delegate = null; + + this.method = "next"; + this.arg = undefined; + + this.tryEntries.forEach(resetTryEntry); + + if (!skipTempReset) { + for (var name in this) { + // Not sure about the optimal order of these conditions: + if (name.charAt(0) === "t" && + hasOwn.call(this, name) && + !isNaN(+name.slice(1))) { + this[name] = undefined; + } + } + } + }, + + stop: function() { + this.done = true; + + var rootEntry = this.tryEntries[0]; + var rootRecord = rootEntry.completion; + if (rootRecord.type === "throw") { + throw rootRecord.arg; + } + + return this.rval; + }, + + dispatchException: function(exception) { + if (this.done) { + throw exception; + } + + var context = this; + function handle(loc, caught) { + record.type = "throw"; + record.arg = exception; + context.next = loc; + + if (caught) { + // If the dispatched exception was caught by a catch block, + // then let that catch block handle the exception normally. + context.method = "next"; + context.arg = undefined; + } + + return !! caught; + } + + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + var record = entry.completion; + + if (entry.tryLoc === "root") { + // Exception thrown outside of any try block that could handle + // it, so set the completion value of the entire function to + // throw the exception. + return handle("end"); + } + + if (entry.tryLoc <= this.prev) { + var hasCatch = hasOwn.call(entry, "catchLoc"); + var hasFinally = hasOwn.call(entry, "finallyLoc"); + + if (hasCatch && hasFinally) { + if (this.prev < entry.catchLoc) { + return handle(entry.catchLoc, true); + } else if (this.prev < entry.finallyLoc) { + return handle(entry.finallyLoc); + } + + } else if (hasCatch) { + if (this.prev < entry.catchLoc) { + return handle(entry.catchLoc, true); + } + + } else if (hasFinally) { + if (this.prev < entry.finallyLoc) { + return handle(entry.finallyLoc); + } + + } else { + throw new Error("try statement without catch or finally"); + } + } + } + }, + + abrupt: function(type, arg) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.tryLoc <= this.prev && + hasOwn.call(entry, "finallyLoc") && + this.prev < entry.finallyLoc) { + var finallyEntry = entry; + break; + } + } + + if (finallyEntry && + (type === "break" || + type === "continue") && + finallyEntry.tryLoc <= arg && + arg <= finallyEntry.finallyLoc) { + // Ignore the finally entry if control is not jumping to a + // location outside the try/catch block. + finallyEntry = null; + } + + var record = finallyEntry ? finallyEntry.completion : {}; + record.type = type; + record.arg = arg; + + if (finallyEntry) { + this.method = "next"; + this.next = finallyEntry.finallyLoc; + return ContinueSentinel; + } + + return this.complete(record); + }, + + complete: function(record, afterLoc) { + if (record.type === "throw") { + throw record.arg; + } + + if (record.type === "break" || + record.type === "continue") { + this.next = record.arg; + } else if (record.type === "return") { + this.rval = this.arg = record.arg; + this.method = "return"; + this.next = "end"; + } else if (record.type === "normal" && afterLoc) { + this.next = afterLoc; + } + + return ContinueSentinel; + }, + + finish: function(finallyLoc) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.finallyLoc === finallyLoc) { + this.complete(entry.completion, entry.afterLoc); + resetTryEntry(entry); + return ContinueSentinel; + } + } + }, + + "catch": function(tryLoc) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + if (entry.tryLoc === tryLoc) { + var record = entry.completion; + if (record.type === "throw") { + var thrown = record.arg; + resetTryEntry(entry); + } + return thrown; + } + } + + // The context.catch method must only be called with a location + // argument that corresponds to a known catch block. + throw new Error("illegal catch attempt"); + }, + + delegateYield: function(iterable, resultName, nextLoc) { + this.delegate = { + iterator: values(iterable), + resultName: resultName, + nextLoc: nextLoc + }; + + if (this.method === "next") { + // Deliberately forget the last sent value so that we don't + // accidentally pass it on to the delegate. + this.arg = undefined; + } + + return ContinueSentinel; + } + }; +})( + // In sloppy mode, unbound `this` refers to the global object, fallback to + // Function constructor if we're in global strict mode. That is sadly a form + // of indirect eval which violates Content Security Policy. + (function() { return this })() || Function("return this")() +); + + +/***/ }), +/* 297 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Model; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_keys__ = __webpack_require__(59); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_lodash_keys___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_lodash_keys__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual__ = __webpack_require__(75); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_lodash_isEqual___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_lodash_isEqual__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_lodash_map__ = __webpack_require__(358); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_lodash_map___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_lodash_map__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_lodash_every__ = __webpack_require__(380); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_lodash_every___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_lodash_every__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_lodash_find__ = __webpack_require__(383); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_lodash_find___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_lodash_find__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_bluebird__ = __webpack_require__(388); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_bluebird___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_bluebird__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_axios__ = __webpack_require__(391); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_axios___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_axios__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_performance_now__ = __webpack_require__(409); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_performance_now___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_performance_now__); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__layers__ = __webpack_require__(114); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__visualizations__ = __webpack_require__(541); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__Tensor__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__WebGL2__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__proto__ = __webpack_require__(543); + + + + + + +function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _next(value) { step("next", value); } function _throw(err) { step("throw", err); } _next(); }); }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + + + + + + + + + +var axiosSource = __WEBPACK_IMPORTED_MODULE_6_axios___default.a.CancelToken.source(); + +var Model = function () { + function Model() { + var _this = this; + + var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, Model); + + var _config$filepath = config.filepath, + filepath = _config$filepath === void 0 ? null : _config$filepath, + _config$headers = config.headers, + headers = _config$headers === void 0 ? {} : _config$headers, + _config$filesystem = config.filesystem, + filesystem = _config$filesystem === void 0 ? false : _config$filesystem, + _config$gpu = config.gpu, + gpu = _config$gpu === void 0 ? false : _config$gpu, + _config$transferLayer = config.transferLayerOutputs, + transferLayerOutputs = _config$transferLayer === void 0 ? false : _config$transferLayer, + _config$pauseAfterLay = config.pauseAfterLayerCalls, + pauseAfterLayerCalls = _config$pauseAfterLay === void 0 ? false : _config$pauseAfterLay, + _config$visualization = config.visualizations, + visualizations = _config$visualization === void 0 ? [] : _config$visualization; + + if (!filepath) { + throw new Error('[Model] path to protobuf-serialized model definition file is missing.'); + } + + this.filepath = filepath; + this.headers = headers; + this.filesystem = typeof window !== 'undefined' ? false : filesystem; + this.dataRequestProgress = 0; + this.id = null; + this.name = null; + this.kerasVersion = null; + this.backend = null; + this.modelConfig = {}; + this.modelWeights = []; + this.gpu = typeof window !== 'undefined' && __WEBPACK_IMPORTED_MODULE_11__WebGL2__["b" /* webgl2 */].isSupported ? gpu : false; + this.transferLayerOutputs = transferLayerOutputs; + this.pauseAfterLayerCalls = pauseAfterLayerCalls; + this.modelLayersMap = new Map(); + this.inputTensorsMap = new Map(); + this.inputLayerNames = []; + this.outputLayerNames = []; + this.finishedLayerNames = []; + this.isRunning = false; + this.predictStats = {}; + this.visMap = new Map(); + visualizations.forEach(function (v) { + if (v in __WEBPACK_IMPORTED_MODULE_9__visualizations__) { + var visInstance = new __WEBPACK_IMPORTED_MODULE_9__visualizations__[v]({ + modelLayersMap: _this.modelLayersMap, + gpu: _this.gpu + }); + + _this.visMap.set(v, visInstance); + } + }); + this._ready = this._initialize(); + } + + _createClass(Model, [{ + key: "checkGPUSupport", + value: function checkGPUSupport() { + return __WEBPACK_IMPORTED_MODULE_11__WebGL2__["b" /* webgl2 */].isSupported; + } + }, { + key: "ready", + value: function ready() { + return this._ready; + } + }, { + key: "_interrupt", + value: function _interrupt() { + axiosSource.cancel(); + } + }, { + key: "_initialize", + value: function () { + var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee() { + var _this2 = this; + + var req; + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + _context.prev = 0; + req = this.filesystem ? this._dataRequestFS() : this._dataRequestHTTP(this.headers); + _context.next = 4; + return req; + + case 4: + _context.next = 10; + break; + + case 6: + _context.prev = 6; + _context.t0 = _context["catch"](0); + console.log(_context.t0); + + this._interrupt(); + + case 10: + this._buildDAG(); + + this.inputLayerNames.forEach(function (name) { + var inputLayer = _this2.modelLayersMap.get(name); + + inputLayer.call(_this2.inputTensorsMap.get(name)); + inputLayer.hasOutput = true; + inputLayer.visited = true; + }); + _context.next = 14; + return this._traverseDAG(this.inputLayerNames); + + case 14: + this.finishedLayerNames = []; + this.modelLayersMap.forEach(function (layer) { + layer.hasOutput = false; + layer.visited = false; + }); + this.visMap.forEach(function (visInstance) { + visInstance.initialize(); + }); + return _context.abrupt("return", true); + + case 18: + case "end": + return _context.stop(); + } + } + }, _callee, this, [[0, 6]]); + })); + + function _initialize() { + return _ref.apply(this, arguments); + } + + return _initialize; + }() + }, { + key: "_dataRequestHTTP", + value: function () { + var _ref2 = _asyncToGenerator(regeneratorRuntime.mark(function _callee2() { + var _this3 = this; + + var headers, + res, + _args2 = arguments; + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + headers = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : {}; + _context2.prev = 1; + _context2.next = 4; + return __WEBPACK_IMPORTED_MODULE_6_axios___default.a.get(this.filepath, { + responseType: 'arraybuffer', + headers: headers, + onDownloadProgress: function onDownloadProgress(e) { + if (e.lengthComputable) { + var percentComplete = Math.round(100 * e.loaded / e.total); + _this3.dataRequestProgress = percentComplete; + } + }, + cancelToken: axiosSource.token + }); + + case 4: + res = _context2.sent; + this.decodeProtobuf(new Uint8Array(res.data)); + _context2.next = 15; + break; + + case 8: + _context2.prev = 8; + _context2.t0 = _context2["catch"](1); + + if (!__WEBPACK_IMPORTED_MODULE_6_axios___default.a.isCancel(_context2.t0)) { + _context2.next = 14; + break; + } + + console.log('[Model] Data request canceled', _context2.t0.message); + _context2.next = 15; + break; + + case 14: + throw _context2.t0; + + case 15: + this.dataRequestProgress = 100; + + case 16: + case "end": + return _context2.stop(); + } + } + }, _callee2, this, [[1, 8]]); + })); + + function _dataRequestHTTP() { + return _ref2.apply(this, arguments); + } + + return _dataRequestHTTP; + }() + }, { + key: "_dataRequestFS", + value: function () { + var _ref3 = _asyncToGenerator(regeneratorRuntime.mark(function _callee3() { + var readFile, file; + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) { + switch (_context3.prev = _context3.next) { + case 0: + readFile = __WEBPACK_IMPORTED_MODULE_5_bluebird___default.a.promisify(__webpack_require__(559).readFile); + _context3.prev = 1; + _context3.next = 4; + return readFile(this.filepath); + + case 4: + file = _context3.sent; + this.decodeProtobuf(file); + _context3.next = 11; + break; + + case 8: + _context3.prev = 8; + _context3.t0 = _context3["catch"](1); + throw _context3.t0; + + case 11: + this.dataRequestProgress = 100; + + case 12: + case "end": + return _context3.stop(); + } + } + }, _callee3, this, [[1, 8]]); + })); + + function _dataRequestFS() { + return _ref3.apply(this, arguments); + } + + return _dataRequestFS; + }() + }, { + key: "decodeProtobuf", + value: function decodeProtobuf(buffer) { + var err = __WEBPACK_IMPORTED_MODULE_12__proto__["a" /* default */].Model.verify(buffer); + + if (err) { + throw new Error("[Model] Invalid model - check protobuf serialization: {err}"); + } + + var model = __WEBPACK_IMPORTED_MODULE_12__proto__["a" /* default */].Model.decode(buffer); + this.id = model.id; + this.name = model.name; + this.kerasVersion = model.kerasVersion; + this.backend = model.backend; + this.modelConfig = JSON.parse(model.modelConfig); + this.modelWeights = model.modelWeights; + } + }, { + key: "getLoadingProgress", + value: function getLoadingProgress() { + return this.dataRequestProgress; + } + }, { + key: "toggleGPU", + value: function toggleGPU(mode) { + var _this4 = this; + + if (typeof mode === 'undefined') { + this.gpu = !this.gpu; + } else { + this.gpu = mode; + } + + this.modelLayersMap.forEach(function (layer) { + layer.toggleGPU(_this4.gpu); + }); + this.visMap.forEach(function (visInstance) { + visInstance.gpu = _this4.gpu; + }); + this.resetInputTensors(); + } + }, { + key: "resetInputTensors", + value: function resetInputTensors() { + var _this5 = this; + + this.inputLayerNames.forEach(function (name) { + var inputLayer = _this5.modelLayersMap.get(name); + + _this5.inputTensorsMap.set(name, new __WEBPACK_IMPORTED_MODULE_10__Tensor__["a" /* default */]([], inputLayer.shape)); + }); + } + }, { + key: "_buildDAG", + value: function _buildDAG() { + var _this6 = this; + + var modelClass = this.modelConfig.class_name; + var modelConfig = []; + + if (modelClass === 'Sequential') { + modelConfig = this.modelConfig.config; + } else if (modelClass === 'Model') { + modelConfig = this.modelConfig.config.layers; + } + + if (!(Array.isArray(modelConfig) && modelConfig.length)) { + throw new Error('[Model] Model configuration does not contain any layers.'); + } + + modelConfig.forEach(function (layerDef, index) { + var layerClass = layerDef.class_name; + var layerConfig = layerDef.config; + + if (modelClass === 'Model' && layerClass === 'Sequential') { + layerConfig.forEach(function (branchLayerDef, branchIndex) { + var branchLayerClass = branchLayerDef.class_name; + var branchLayerConfig = branchLayerDef.config; + var branchInboundLayerNames = branchIndex === 0 ? layerDef.inbound_nodes[0].map(function (node) { + return node[0]; + }) : [layerConfig[branchIndex - 1].config.name]; + + _this6._createLayer(branchLayerClass, branchLayerConfig, branchInboundLayerNames); + }); + } else if (!(layerClass in __WEBPACK_IMPORTED_MODULE_8__layers__)) { + throw new Error("[Model] Layer ".concat(layerClass, " specified in model configuration is not implemented!")); + } else { + if (modelClass === 'Sequential' && index === 0) { + var inputName = 'input'; + var inputShape = layerConfig.batch_input_shape.slice(1); + var layer = new __WEBPACK_IMPORTED_MODULE_8__layers__["InputLayer"]({ + name: inputName, + shape: inputShape, + gpu: _this6.gpu + }); + + _this6.modelLayersMap.set(inputName, layer); + + _this6.inputTensorsMap.set(inputName, new __WEBPACK_IMPORTED_MODULE_10__Tensor__["a" /* default */]([], inputShape)); + + _this6.inputLayerNames.push(inputName); + } else if (modelClass === 'Model' && layerClass === 'InputLayer') { + var _inputShape = layerConfig.batch_input_shape.slice(1); + + _this6.inputTensorsMap.set(layerConfig.name, new __WEBPACK_IMPORTED_MODULE_10__Tensor__["a" /* default */]([], _inputShape)); + + _this6.inputLayerNames.push(layerConfig.name); + } + + var inboundLayerNames = []; + + if (modelClass === 'Sequential') { + if (index === 0) { + inboundLayerNames = ['input']; + } else { + inboundLayerNames = [modelConfig[index - 1].config.name]; + } + } else if (modelClass === 'Model') { + var inboundNodes = layerDef.inbound_nodes; + + if (inboundNodes && inboundNodes.length) { + inboundLayerNames = inboundNodes[0].map(function (node) { + return node[0]; + }); + } + } + + _this6._createLayer(layerClass, layerConfig, inboundLayerNames); + } + }); + this.modelLayersMap.forEach(function (layer) { + if (layer.outbound.length === 0) { + _this6.outputLayerNames.push(layer.name); + } + }); + this.inputLayerNames.sort(); + this.outputLayerNames.sort(); + } + }, { + key: "_createLayer", + value: function _createLayer(layerClass, layerConfig, inboundLayerNames) { + var _this7 = this; + + var layer = new __WEBPACK_IMPORTED_MODULE_8__layers__[layerClass](Object.assign({}, layerConfig, { + gpu: this.gpu + })); + var weightNames = []; + + if (layerClass === 'Bidirectional') { + var forwardWeightNames = layer.forwardLayer.params.map(function (param) { + return "".concat(layerConfig.name, "/forward_").concat(layerConfig.layer.config.name, "/").concat(param); + }); + var backwardWeightNames = layer.backwardLayer.params.map(function (param) { + return "".concat(layerConfig.name, "/backward_").concat(layerConfig.layer.config.name, "/").concat(param); + }); + weightNames = forwardWeightNames.concat(backwardWeightNames); + } else if (layerClass === 'TimeDistributed') { + weightNames = layer.layer.params.map(function (param) { + return "".concat(layerConfig.name, "/").concat(param); + }); + } else { + weightNames = layer.params.map(function (param) { + return "".concat(layerConfig.name, "/").concat(param); + }); + } + + if (weightNames && weightNames.length) { + var weights = weightNames.map(function (weightName) { + var weightDef = __WEBPACK_IMPORTED_MODULE_4_lodash_find___default()(_this7.modelWeights, function (w) { + var weightRE = new RegExp("^".concat(weightName)); + return weightRE.test(w.weightName); + }); + + if (!weightDef) { + throw new Error("[Model] error loading weights."); + } + + var data = weightDef.data, + shape = weightDef.shape, + type = weightDef.type; + var buf = new ArrayBuffer(data.byteLength); + var arr = new Uint8Array(buf); + arr.set(new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); + + if (type === 'uint8') { + var quantizeMin = weightDef.quantizeMin, + quantizeMax = weightDef.quantizeMax; + var unquantized = new Float32Array(arr); + + for (var i = 0, len = unquantized.length; i < len; i++) { + unquantized[i] *= (quantizeMax - quantizeMin) / 255; + unquantized[i] += quantizeMin; + } + + return new __WEBPACK_IMPORTED_MODULE_10__Tensor__["a" /* default */](unquantized, shape); + } else { + return new __WEBPACK_IMPORTED_MODULE_10__Tensor__["a" /* default */](new Float32Array(buf), shape); + } + }); + layer.setWeights(weights); + } + + this.modelLayersMap.set(layerConfig.name, layer); + inboundLayerNames.forEach(function (layerName) { + _this7.modelLayersMap.get(layerConfig.name).inbound.push(layerName); + + _this7.modelLayersMap.get(layerName).outbound.push(layerConfig.name); + }); + } + }, { + key: "_traverseDAG", + value: function () { + var _ref4 = _asyncToGenerator(regeneratorRuntime.mark(function _callee4(nodes) { + var _this8 = this; + + var node, currentLayer, _currentLayer, inboundLayers; + + return regeneratorRuntime.wrap(function _callee4$(_context4) { + while (1) { + switch (_context4.prev = _context4.next) { + case 0: + if (!(nodes.length === 0)) { + _context4.next = 4; + break; + } + + return _context4.abrupt("return", true); + + case 4: + if (!(nodes.length === 1)) { + _context4.next = 28; + break; + } + + node = nodes[0]; + currentLayer = this.modelLayersMap.get(node); + + if (!(currentLayer.layerClass === 'InputLayer')) { + _context4.next = 11; + break; + } + + this.finishedLayerNames.push(this.modelLayersMap.get(node).name); + _context4.next = 24; + break; + + case 11: + _currentLayer = this.modelLayersMap.get(node); + + if (!_currentLayer.visited) { + _context4.next = 14; + break; + } + + return _context4.abrupt("return", false); + + case 14: + inboundLayers = _currentLayer.inbound.map(function (n) { + return _this8.modelLayersMap.get(n); + }); + + if (__WEBPACK_IMPORTED_MODULE_3_lodash_every___default()(__WEBPACK_IMPORTED_MODULE_2_lodash_map___default()(inboundLayers, 'hasOutput'))) { + _context4.next = 17; + break; + } + + return _context4.abrupt("return", false); + + case 17: + if (_currentLayer.isMergeLayer) { + _currentLayer.call(__WEBPACK_IMPORTED_MODULE_2_lodash_map___default()(inboundLayers, 'output')); + } else { + _currentLayer.call(inboundLayers[0].output); + } + + _currentLayer.hasOutput = true; + _currentLayer.visited = true; + this.finishedLayerNames.push(_currentLayer.name); + + if (!this.pauseAfterLayerCalls) { + _context4.next = 24; + break; + } + + _context4.next = 24; + return __WEBPACK_IMPORTED_MODULE_5_bluebird___default.a.delay(0); + + case 24: + _context4.next = 26; + return this._traverseDAG(currentLayer.outbound); + + case 26: + _context4.next = 30; + break; + + case 28: + _context4.next = 30; + return __WEBPACK_IMPORTED_MODULE_5_bluebird___default.a.all(nodes.map(function (node) { + return _this8._traverseDAG([node]); + })); + + case 30: + case "end": + return _context4.stop(); + } + } + }, _callee4, this); + })); + + function _traverseDAG(_x) { + return _ref4.apply(this, arguments); + } + + return _traverseDAG; + }() + }, { + key: "_maybeTransferIntermediateOutputs", + value: function _maybeTransferIntermediateOutputs() { + if (this.gpu && this.transferLayerOutputs) { + this.modelLayersMap.forEach(function (layer) { + if (layer.output && layer.output.glTexture) { + __WEBPACK_IMPORTED_MODULE_11__WebGL2__["b" /* webgl2 */].bindOutputTexture(layer.output.glTexture, layer.output.glTextureShape); + layer.output.transferFromGLTexture(); + + if (layer.output.is2DReshaped) { + layer.output.reshapeFrom2D(); + } + } + }); + } + } + }, { + key: "loadData", + value: function loadData(inputData) { + var _this9 = this; + + this.inputLayerNames.forEach(function (name) { + var inputLayer = _this9.modelLayersMap.get(name); + + _this9.inputTensorsMap.get(name).replaceTensorData(inputData[name]); + + inputLayer.call(_this9.inputTensorsMap.get(name)); + inputLayer.hasOutput = true; + inputLayer.visited = true; + }); + } + }, { + key: "predict", + value: function () { + var _ref5 = _asyncToGenerator(regeneratorRuntime.mark(function _callee5(inputData) { + var _this10 = this; + + var start, modelClass, outputData, outputLayer; + return regeneratorRuntime.wrap(function _callee5$(_context5) { + while (1) { + switch (_context5.prev = _context5.next) { + case 0: + this.isRunning = true; + + if (__WEBPACK_IMPORTED_MODULE_1_lodash_isEqual___default()(__WEBPACK_IMPORTED_MODULE_0_lodash_keys___default()(inputData).sort(), this.inputLayerNames)) { + _context5.next = 4; + break; + } + + this.isRunning = false; + throw new Error('[Model] predict() must take an object where the keys are the named inputs of the model: ' + JSON.stringify(this.inputLayerNames)); + + case 4: + if (__WEBPACK_IMPORTED_MODULE_3_lodash_every___default()(this.inputLayerNames, function (name) { + return inputData[name] instanceof Float32Array; + })) { + _context5.next = 7; + break; + } + + this.isRunning = false; + throw new Error('[Model] predict() must take an object where the values are the flattened data as Float32Array.'); + + case 7: + this.finishedLayerNames = []; + this.modelLayersMap.forEach(function (layer) { + layer.hasOutput = false; + layer.visited = false; + }); + start = __WEBPACK_IMPORTED_MODULE_7_performance_now___default()(); + this.loadData(inputData); + this.predictStats.loadData = __WEBPACK_IMPORTED_MODULE_7_performance_now___default()() - start; + start = __WEBPACK_IMPORTED_MODULE_7_performance_now___default()(); + _context5.next = 15; + return this._traverseDAG(this.inputLayerNames); + + case 15: + this.predictStats.forwardPass = __WEBPACK_IMPORTED_MODULE_7_performance_now___default()() - start; + + this._maybeTransferIntermediateOutputs(); + + modelClass = this.modelConfig.class_name; + outputData = {}; + + if (modelClass === 'Sequential') { + outputLayer = this.modelLayersMap.get(this.outputLayerNames[0]); + outputData['output'] = outputLayer.output.tensor.data; + } else if (modelClass === 'Model') { + this.outputLayerNames.forEach(function (layerName) { + var outputLayer = _this10.modelLayersMap.get(layerName); + + outputData[layerName] = outputLayer.output.tensor.data; + }); + } + + start = __WEBPACK_IMPORTED_MODULE_7_performance_now___default()(); + this.visMap.forEach(function (visInstance) { + visInstance.update(); + }); + this.predictStats.visualizations = __WEBPACK_IMPORTED_MODULE_7_performance_now___default()() - start; + this.isRunning = false; + return _context5.abrupt("return", outputData); + + case 25: + case "end": + return _context5.stop(); + } + } + }, _callee5, this); + })); + + function predict(_x2) { + return _ref5.apply(this, arguments); + } + + return predict; + }() + }, { + key: "layerCall", + value: function layerCall(layerName, input) { + if (!this.modelLayersMap.has(layerName)) return; + var x; + + if (input instanceof __WEBPACK_IMPORTED_MODULE_10__Tensor__["a" /* default */]) { + x = input; + } else { + x = new __WEBPACK_IMPORTED_MODULE_10__Tensor__["a" /* default */](input.data, input.shape); + } + + var layer = this.modelLayersMap.get(layerName); + return layer.call(x); + } + }, { + key: "cleanup", + value: function cleanup() { + __WEBPACK_IMPORTED_MODULE_11__WebGL2__["b" /* webgl2 */].clearRefs(); + this.modelLayersMap.clear(); + this.inputTensorsMap.clear(); + this.visMap.clear(); + delete this.modelWeights; + } + }]); + + return Model; +}(); + + + +/***/ }), +/* 298 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseTimes = __webpack_require__(299), + isArguments = __webpack_require__(105), + isArray = __webpack_require__(17), + isBuffer = __webpack_require__(142), + isIndex = __webpack_require__(106), + isTypedArray = __webpack_require__(143); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; +} + +module.exports = arrayLikeKeys; + + +/***/ }), +/* 299 */ +/***/ (function(module, exports) { + +/** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ +function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +module.exports = baseTimes; + + +/***/ }), +/* 300 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseGetTag = __webpack_require__(60), + isObjectLike = __webpack_require__(62); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]'; + +/** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ +function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; +} + +module.exports = baseIsArguments; + + +/***/ }), +/* 301 */ +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(61); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +module.exports = getRawTag; + + +/***/ }), +/* 302 */ +/***/ (function(module, exports) { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString(value) { + return nativeObjectToString.call(value); +} + +module.exports = objectToString; + + +/***/ }), +/* 303 */ +/***/ (function(module, exports) { + +/** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ +function stubFalse() { + return false; +} + +module.exports = stubFalse; + + +/***/ }), +/* 304 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseGetTag = __webpack_require__(60), + isLength = __webpack_require__(107), + isObjectLike = __webpack_require__(62); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values of typed arrays. */ +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = +typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = +typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = +typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = +typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag] = typedArrayTags[arrayTag] = +typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = +typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = +typedArrayTags[errorTag] = typedArrayTags[funcTag] = +typedArrayTags[mapTag] = typedArrayTags[numberTag] = +typedArrayTags[objectTag] = typedArrayTags[regexpTag] = +typedArrayTags[setTag] = typedArrayTags[stringTag] = +typedArrayTags[weakMapTag] = false; + +/** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ +function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; +} + +module.exports = baseIsTypedArray; + + +/***/ }), +/* 305 */ +/***/ (function(module, exports) { + +/** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ +function baseUnary(func) { + return function(value) { + return func(value); + }; +} + +module.exports = baseUnary; + + +/***/ }), +/* 306 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module) {var freeGlobal = __webpack_require__(141); + +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Detect free variable `process` from Node.js. */ +var freeProcess = moduleExports && freeGlobal.process; + +/** Used to access faster Node.js helpers. */ +var nodeUtil = (function() { + try { + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} +}()); + +module.exports = nodeUtil; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(74)(module))) + +/***/ }), +/* 307 */ +/***/ (function(module, exports, __webpack_require__) { + +var isPrototype = __webpack_require__(308), + nativeKeys = __webpack_require__(309); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; +} + +module.exports = baseKeys; + + +/***/ }), +/* 308 */ +/***/ (function(module, exports) { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; +} + +module.exports = isPrototype; + + +/***/ }), +/* 309 */ +/***/ (function(module, exports, __webpack_require__) { + +var overArg = __webpack_require__(310); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeKeys = overArg(Object.keys, Object); + +module.exports = nativeKeys; + + +/***/ }), +/* 310 */ +/***/ (function(module, exports) { + +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +module.exports = overArg; + + +/***/ }), +/* 311 */ +/***/ (function(module, exports, __webpack_require__) { + +var Stack = __webpack_require__(145), + equalArrays = __webpack_require__(147), + equalByTag = __webpack_require__(343), + equalObjects = __webpack_require__(347), + getTag = __webpack_require__(353), + isArray = __webpack_require__(17), + isBuffer = __webpack_require__(142), + isTypedArray = __webpack_require__(143); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); +} + +module.exports = baseIsEqualDeep; + + +/***/ }), +/* 312 */ +/***/ (function(module, exports) { + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} + +module.exports = listCacheClear; + + +/***/ }), +/* 313 */ +/***/ (function(module, exports, __webpack_require__) { + +var assocIndexOf = __webpack_require__(77); + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} + +module.exports = listCacheDelete; + + +/***/ }), +/* 314 */ +/***/ (function(module, exports, __webpack_require__) { + +var assocIndexOf = __webpack_require__(77); + +/** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +module.exports = listCacheGet; + + +/***/ }), +/* 315 */ +/***/ (function(module, exports, __webpack_require__) { + +var assocIndexOf = __webpack_require__(77); + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; +} + +module.exports = listCacheHas; + + +/***/ }), +/* 316 */ +/***/ (function(module, exports, __webpack_require__) { + +var assocIndexOf = __webpack_require__(77); + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +module.exports = listCacheSet; + + +/***/ }), +/* 317 */ +/***/ (function(module, exports, __webpack_require__) { + +var ListCache = __webpack_require__(76); + +/** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear() { + this.__data__ = new ListCache; + this.size = 0; +} + +module.exports = stackClear; + + +/***/ }), +/* 318 */ +/***/ (function(module, exports) { + +/** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; +} + +module.exports = stackDelete; + + +/***/ }), +/* 319 */ +/***/ (function(module, exports) { + +/** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function stackGet(key) { + return this.__data__.get(key); +} + +module.exports = stackGet; + + +/***/ }), +/* 320 */ +/***/ (function(module, exports) { + +/** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function stackHas(key) { + return this.__data__.has(key); +} + +module.exports = stackHas; + + +/***/ }), +/* 321 */ +/***/ (function(module, exports, __webpack_require__) { + +var ListCache = __webpack_require__(76), + Map = __webpack_require__(110), + MapCache = __webpack_require__(111); + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ +function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; +} + +module.exports = stackSet; + + +/***/ }), +/* 322 */ +/***/ (function(module, exports, __webpack_require__) { + +var isFunction = __webpack_require__(144), + isMasked = __webpack_require__(323), + isObject = __webpack_require__(64), + toSource = __webpack_require__(146); + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); +} + +module.exports = baseIsNative; + + +/***/ }), +/* 323 */ +/***/ (function(module, exports, __webpack_require__) { + +var coreJsData = __webpack_require__(324); + +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +module.exports = isMasked; + + +/***/ }), +/* 324 */ +/***/ (function(module, exports, __webpack_require__) { + +var root = __webpack_require__(22); + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +module.exports = coreJsData; + + +/***/ }), +/* 325 */ +/***/ (function(module, exports) { + +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} + +module.exports = getValue; + + +/***/ }), +/* 326 */ +/***/ (function(module, exports, __webpack_require__) { + +var Hash = __webpack_require__(327), + ListCache = __webpack_require__(76), + Map = __webpack_require__(110); + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; +} + +module.exports = mapCacheClear; + + +/***/ }), +/* 327 */ +/***/ (function(module, exports, __webpack_require__) { + +var hashClear = __webpack_require__(328), + hashDelete = __webpack_require__(329), + hashGet = __webpack_require__(330), + hashHas = __webpack_require__(331), + hashSet = __webpack_require__(332); + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `Hash`. +Hash.prototype.clear = hashClear; +Hash.prototype['delete'] = hashDelete; +Hash.prototype.get = hashGet; +Hash.prototype.has = hashHas; +Hash.prototype.set = hashSet; + +module.exports = Hash; + + +/***/ }), +/* 328 */ +/***/ (function(module, exports, __webpack_require__) { + +var nativeCreate = __webpack_require__(78); + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; +} + +module.exports = hashClear; + + +/***/ }), +/* 329 */ +/***/ (function(module, exports) { + +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} + +module.exports = hashDelete; + + +/***/ }), +/* 330 */ +/***/ (function(module, exports, __webpack_require__) { + +var nativeCreate = __webpack_require__(78); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; +} + +module.exports = hashGet; + + +/***/ }), +/* 331 */ +/***/ (function(module, exports, __webpack_require__) { + +var nativeCreate = __webpack_require__(78); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); +} + +module.exports = hashHas; + + +/***/ }), +/* 332 */ +/***/ (function(module, exports, __webpack_require__) { + +var nativeCreate = __webpack_require__(78); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; +} + +module.exports = hashSet; + + +/***/ }), +/* 333 */ +/***/ (function(module, exports, __webpack_require__) { + +var getMapData = __webpack_require__(79); + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; +} + +module.exports = mapCacheDelete; + + +/***/ }), +/* 334 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +module.exports = isKeyable; + + +/***/ }), +/* 335 */ +/***/ (function(module, exports, __webpack_require__) { + +var getMapData = __webpack_require__(79); + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet(key) { + return getMapData(this, key).get(key); +} + +module.exports = mapCacheGet; + + +/***/ }), +/* 336 */ +/***/ (function(module, exports, __webpack_require__) { + +var getMapData = __webpack_require__(79); + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas(key) { + return getMapData(this, key).has(key); +} + +module.exports = mapCacheHas; + + +/***/ }), +/* 337 */ +/***/ (function(module, exports, __webpack_require__) { + +var getMapData = __webpack_require__(79); + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} + +module.exports = mapCacheSet; + + +/***/ }), +/* 338 */ +/***/ (function(module, exports, __webpack_require__) { + +var MapCache = __webpack_require__(111), + setCacheAdd = __webpack_require__(339), + setCacheHas = __webpack_require__(340); + +/** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ +function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } +} + +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; + +module.exports = SetCache; + + +/***/ }), +/* 339 */ +/***/ (function(module, exports) { + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; +} + +module.exports = setCacheAdd; + + +/***/ }), +/* 340 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ +function setCacheHas(value) { + return this.__data__.has(value); +} + +module.exports = setCacheHas; + + +/***/ }), +/* 341 */ +/***/ (function(module, exports) { + +/** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ +function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} + +module.exports = arraySome; + + +/***/ }), +/* 342 */ +/***/ (function(module, exports) { + +/** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function cacheHas(cache, key) { + return cache.has(key); +} + +module.exports = cacheHas; + + +/***/ }), +/* 343 */ +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(61), + Uint8Array = __webpack_require__(344), + eq = __webpack_require__(109), + equalArrays = __webpack_require__(147), + mapToArray = __webpack_require__(345), + setToArray = __webpack_require__(346); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + mapTag = '[object Map]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]'; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; + +/** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; +} + +module.exports = equalByTag; + + +/***/ }), +/* 344 */ +/***/ (function(module, exports, __webpack_require__) { + +var root = __webpack_require__(22); + +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; + +module.exports = Uint8Array; + + +/***/ }), +/* 345 */ +/***/ (function(module, exports) { + +/** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ +function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} + +module.exports = mapToArray; + + +/***/ }), +/* 346 */ +/***/ (function(module, exports) { + +/** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ +function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} + +module.exports = setToArray; + + +/***/ }), +/* 347 */ +/***/ (function(module, exports, __webpack_require__) { + +var getAllKeys = __webpack_require__(348); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked && stack.get(other)) { + return stacked == other; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; +} + +module.exports = equalObjects; + + +/***/ }), +/* 348 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseGetAllKeys = __webpack_require__(349), + getSymbols = __webpack_require__(350), + keys = __webpack_require__(59); + +/** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); +} + +module.exports = getAllKeys; + + +/***/ }), +/* 349 */ +/***/ (function(module, exports, __webpack_require__) { + +var arrayPush = __webpack_require__(148), + isArray = __webpack_require__(17); + +/** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ +function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); +} + +module.exports = baseGetAllKeys; + + +/***/ }), +/* 350 */ +/***/ (function(module, exports, __webpack_require__) { + +var arrayFilter = __webpack_require__(351), + stubArray = __webpack_require__(352); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); +}; + +module.exports = getSymbols; + + +/***/ }), +/* 351 */ +/***/ (function(module, exports) { + +/** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ +function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} + +module.exports = arrayFilter; + + +/***/ }), +/* 352 */ +/***/ (function(module, exports) { + +/** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */ +function stubArray() { + return []; +} + +module.exports = stubArray; + + +/***/ }), +/* 353 */ +/***/ (function(module, exports, __webpack_require__) { + +var DataView = __webpack_require__(354), + Map = __webpack_require__(110), + Promise = __webpack_require__(355), + Set = __webpack_require__(356), + WeakMap = __webpack_require__(357), + baseGetTag = __webpack_require__(60), + toSource = __webpack_require__(146); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + setTag = '[object Set]', + weakMapTag = '[object WeakMap]'; + +var dataViewTag = '[object DataView]'; + +/** Used to detect maps, sets, and weakmaps. */ +var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + +/** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +var getTag = baseGetTag; + +// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. +if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; +} + +module.exports = getTag; + + +/***/ }), +/* 354 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(52), + root = __webpack_require__(22); + +/* Built-in method references that are verified to be native. */ +var DataView = getNative(root, 'DataView'); + +module.exports = DataView; + + +/***/ }), +/* 355 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(52), + root = __webpack_require__(22); + +/* Built-in method references that are verified to be native. */ +var Promise = getNative(root, 'Promise'); + +module.exports = Promise; + + +/***/ }), +/* 356 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(52), + root = __webpack_require__(22); + +/* Built-in method references that are verified to be native. */ +var Set = getNative(root, 'Set'); + +module.exports = Set; + + +/***/ }), +/* 357 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(52), + root = __webpack_require__(22); + +/* Built-in method references that are verified to be native. */ +var WeakMap = getNative(root, 'WeakMap'); + +module.exports = WeakMap; + + +/***/ }), +/* 358 */ +/***/ (function(module, exports, __webpack_require__) { + +var arrayMap = __webpack_require__(149), + baseIteratee = __webpack_require__(80), + baseMap = __webpack_require__(375), + isArray = __webpack_require__(17); + +/** + * Creates an array of values by running each element in `collection` thru + * `iteratee`. The iteratee is invoked with three arguments: + * (value, index|key, collection). + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, + * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, + * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, + * `template`, `trim`, `trimEnd`, `trimStart`, and `words` + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + * @example + * + * function square(n) { + * return n * n; + * } + * + * _.map([4, 8], square); + * // => [16, 64] + * + * _.map({ 'a': 4, 'b': 8 }, square); + * // => [16, 64] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // The `_.property` iteratee shorthand. + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ +function map(collection, iteratee) { + var func = isArray(collection) ? arrayMap : baseMap; + return func(collection, baseIteratee(iteratee, 3)); +} + +module.exports = map; + + +/***/ }), +/* 359 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsMatch = __webpack_require__(360), + getMatchData = __webpack_require__(361), + matchesStrictComparable = __webpack_require__(151); + +/** + * The base implementation of `_.matches` which doesn't clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new spec function. + */ +function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + return matchesStrictComparable(matchData[0][0], matchData[0][1]); + } + return function(object) { + return object === source || baseIsMatch(object, source, matchData); + }; +} + +module.exports = baseMatches; + + +/***/ }), +/* 360 */ +/***/ (function(module, exports, __webpack_require__) { + +var Stack = __webpack_require__(145), + baseIsEqual = __webpack_require__(108); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * The base implementation of `_.isMatch` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to inspect. + * @param {Object} source The object of property values to match. + * @param {Array} matchData The property names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparisons. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ +function baseIsMatch(object, source, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = Object(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var stack = new Stack; + if (customizer) { + var result = customizer(objValue, srcValue, key, object, source, stack); + } + if (!(result === undefined + ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) + : result + )) { + return false; + } + } + } + return true; +} + +module.exports = baseIsMatch; + + +/***/ }), +/* 361 */ +/***/ (function(module, exports, __webpack_require__) { + +var isStrictComparable = __webpack_require__(150), + keys = __webpack_require__(59); + +/** + * Gets the property names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ +function getMatchData(object) { + var result = keys(object), + length = result.length; + + while (length--) { + var key = result[length], + value = object[key]; + + result[length] = [key, value, isStrictComparable(value)]; + } + return result; +} + +module.exports = getMatchData; + + +/***/ }), +/* 362 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsEqual = __webpack_require__(108), + get = __webpack_require__(363), + hasIn = __webpack_require__(369), + isKey = __webpack_require__(112), + isStrictComparable = __webpack_require__(150), + matchesStrictComparable = __webpack_require__(151), + toKey = __webpack_require__(82); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to match. + * @returns {Function} Returns the new spec function. + */ +function baseMatchesProperty(path, srcValue) { + if (isKey(path) && isStrictComparable(srcValue)) { + return matchesStrictComparable(toKey(path), srcValue); + } + return function(object) { + var objValue = get(object, path); + return (objValue === undefined && objValue === srcValue) + ? hasIn(object, path) + : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); + }; +} + +module.exports = baseMatchesProperty; + + +/***/ }), +/* 363 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseGet = __webpack_require__(152); + +/** + * Gets the value at `path` of `object`. If the resolved value is + * `undefined`, the `defaultValue` is returned in its place. + * + * @static + * @memberOf _ + * @since 3.7.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path of the property to get. + * @param {*} [defaultValue] The value returned for `undefined` resolved values. + * @returns {*} Returns the resolved value. + * @example + * + * var object = { 'a': [{ 'b': { 'c': 3 } }] }; + * + * _.get(object, 'a[0].b.c'); + * // => 3 + * + * _.get(object, ['a', '0', 'b', 'c']); + * // => 3 + * + * _.get(object, 'a.b.c', 'default'); + * // => 'default' + */ +function get(object, path, defaultValue) { + var result = object == null ? undefined : baseGet(object, path); + return result === undefined ? defaultValue : result; +} + +module.exports = get; + + +/***/ }), +/* 364 */ +/***/ (function(module, exports, __webpack_require__) { + +var memoizeCapped = __webpack_require__(365); + +/** Used to match property names within property paths. */ +var reLeadingDot = /^\./, + rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; + +/** Used to match backslashes in property paths. */ +var reEscapeChar = /\\(\\)?/g; + +/** + * Converts `string` to a property path array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the property path array. + */ +var stringToPath = memoizeCapped(function(string) { + var result = []; + if (reLeadingDot.test(string)) { + result.push(''); + } + string.replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; +}); + +module.exports = stringToPath; + + +/***/ }), +/* 365 */ +/***/ (function(module, exports, __webpack_require__) { + +var memoize = __webpack_require__(366); + +/** Used as the maximum memoize cache size. */ +var MAX_MEMOIZE_SIZE = 500; + +/** + * A specialized version of `_.memoize` which clears the memoized function's + * cache when it exceeds `MAX_MEMOIZE_SIZE`. + * + * @private + * @param {Function} func The function to have its output memoized. + * @returns {Function} Returns the new memoized function. + */ +function memoizeCapped(func) { + var result = memoize(func, function(key) { + if (cache.size === MAX_MEMOIZE_SIZE) { + cache.clear(); + } + return key; + }); + + var cache = result.cache; + return result; +} + +module.exports = memoizeCapped; + + +/***/ }), +/* 366 */ +/***/ (function(module, exports, __webpack_require__) { + +var MapCache = __webpack_require__(111); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * Creates a function that memoizes the result of `func`. If `resolver` is + * provided, it determines the cache key for storing the result based on the + * arguments provided to the memoized function. By default, the first argument + * provided to the memoized function is used as the map cache key. The `func` + * is invoked with the `this` binding of the memoized function. + * + * **Note:** The cache is exposed as the `cache` property on the memoized + * function. Its creation may be customized by replacing the `_.memoize.Cache` + * constructor with one whose instances implement the + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) + * method interface of `clear`, `delete`, `get`, `has`, and `set`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] The function to resolve the cache key. + * @returns {Function} Returns the new memoized function. + * @example + * + * var object = { 'a': 1, 'b': 2 }; + * var other = { 'c': 3, 'd': 4 }; + * + * var values = _.memoize(_.values); + * values(object); + * // => [1, 2] + * + * values(other); + * // => [3, 4] + * + * object.a = 2; + * values(object); + * // => [1, 2] + * + * // Modify the result cache. + * values.cache.set(object, ['a', 'b']); + * values(object); + * // => ['a', 'b'] + * + * // Replace `_.memoize.Cache`. + * _.memoize.Cache = WeakMap; + */ +function memoize(func, resolver) { + if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { + throw new TypeError(FUNC_ERROR_TEXT); + } + var memoized = function() { + var args = arguments, + key = resolver ? resolver.apply(this, args) : args[0], + cache = memoized.cache; + + if (cache.has(key)) { + return cache.get(key); + } + var result = func.apply(this, args); + memoized.cache = cache.set(key, result) || cache; + return result; + }; + memoized.cache = new (memoize.Cache || MapCache); + return memoized; +} + +// Expose `MapCache`. +memoize.Cache = MapCache; + +module.exports = memoize; + + +/***/ }), +/* 367 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseToString = __webpack_require__(368); + +/** + * Converts `value` to a string. An empty string is returned for `null` + * and `undefined` values. The sign of `-0` is preserved. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + * @example + * + * _.toString(null); + * // => '' + * + * _.toString(-0); + * // => '-0' + * + * _.toString([1, 2, 3]); + * // => '1,2,3' + */ +function toString(value) { + return value == null ? '' : baseToString(value); +} + +module.exports = toString; + + +/***/ }), +/* 368 */ +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(61), + arrayMap = __webpack_require__(149), + isArray = __webpack_require__(17), + isSymbol = __webpack_require__(81); + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolToString = symbolProto ? symbolProto.toString : undefined; + +/** + * The base implementation of `_.toString` which doesn't convert nullish + * values to empty strings. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + // Exit early for strings to avoid a performance hit in some environments. + if (typeof value == 'string') { + return value; + } + if (isArray(value)) { + // Recursively convert values (susceptible to call stack limits). + return arrayMap(value, baseToString) + ''; + } + if (isSymbol(value)) { + return symbolToString ? symbolToString.call(value) : ''; + } + var result = (value + ''); + return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; +} + +module.exports = baseToString; + + +/***/ }), +/* 369 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseHasIn = __webpack_require__(370), + hasPath = __webpack_require__(371); + +/** + * Checks if `path` is a direct or inherited property of `object`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Object + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + * @example + * + * var object = _.create({ 'a': _.create({ 'b': 2 }) }); + * + * _.hasIn(object, 'a'); + * // => true + * + * _.hasIn(object, 'a.b'); + * // => true + * + * _.hasIn(object, ['a', 'b']); + * // => true + * + * _.hasIn(object, 'b'); + * // => false + */ +function hasIn(object, path) { + return object != null && hasPath(object, path, baseHasIn); +} + +module.exports = hasIn; + + +/***/ }), +/* 370 */ +/***/ (function(module, exports) { + +/** + * The base implementation of `_.hasIn` without support for deep paths. + * + * @private + * @param {Object} [object] The object to query. + * @param {Array|string} key The key to check. + * @returns {boolean} Returns `true` if `key` exists, else `false`. + */ +function baseHasIn(object, key) { + return object != null && key in Object(object); +} + +module.exports = baseHasIn; + + +/***/ }), +/* 371 */ +/***/ (function(module, exports, __webpack_require__) { + +var castPath = __webpack_require__(153), + isArguments = __webpack_require__(105), + isArray = __webpack_require__(17), + isIndex = __webpack_require__(106), + isLength = __webpack_require__(107), + toKey = __webpack_require__(82); + +/** + * Checks if `path` exists on `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Array|string} path The path to check. + * @param {Function} hasFunc The function to check properties. + * @returns {boolean} Returns `true` if `path` exists, else `false`. + */ +function hasPath(object, path, hasFunc) { + path = castPath(path, object); + + var index = -1, + length = path.length, + result = false; + + while (++index < length) { + var key = toKey(path[index]); + if (!(result = object != null && hasFunc(object, key))) { + break; + } + object = object[key]; + } + if (result || ++index != length) { + return result; + } + length = object == null ? 0 : object.length; + return !!length && isLength(length) && isIndex(key, length) && + (isArray(object) || isArguments(object)); +} + +module.exports = hasPath; + + +/***/ }), +/* 372 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseProperty = __webpack_require__(373), + basePropertyDeep = __webpack_require__(374), + isKey = __webpack_require__(112), + toKey = __webpack_require__(82); + +/** + * Creates a function that returns the value at `path` of a given object. + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Util + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + * @example + * + * var objects = [ + * { 'a': { 'b': 2 } }, + * { 'a': { 'b': 1 } } + * ]; + * + * _.map(objects, _.property('a.b')); + * // => [2, 1] + * + * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); + * // => [1, 2] + */ +function property(path) { + return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); +} + +module.exports = property; + + +/***/ }), +/* 373 */ +/***/ (function(module, exports) { + +/** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new accessor function. + */ +function baseProperty(key) { + return function(object) { + return object == null ? undefined : object[key]; + }; +} + +module.exports = baseProperty; + + +/***/ }), +/* 374 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseGet = __webpack_require__(152); + +/** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new accessor function. + */ +function basePropertyDeep(path) { + return function(object) { + return baseGet(object, path); + }; +} + +module.exports = basePropertyDeep; + + +/***/ }), +/* 375 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseEach = __webpack_require__(155), + isArrayLike = __webpack_require__(63); + +/** + * The base implementation of `_.map` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; +} + +module.exports = baseMap; + + +/***/ }), +/* 376 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseFor = __webpack_require__(377), + keys = __webpack_require__(59); + +/** + * The base implementation of `_.forOwn` without support for iteratee shorthands. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ +function baseForOwn(object, iteratee) { + return object && baseFor(object, iteratee, keys); +} + +module.exports = baseForOwn; + + +/***/ }), +/* 377 */ +/***/ (function(module, exports, __webpack_require__) { + +var createBaseFor = __webpack_require__(378); + +/** + * The base implementation of `baseForOwn` which iterates over `object` + * properties returned by `keysFunc` and invokes `iteratee` for each property. + * Iteratee functions may exit iteration early by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ +var baseFor = createBaseFor(); + +module.exports = baseFor; + + +/***/ }), +/* 378 */ +/***/ (function(module, exports) { + +/** + * Creates a base function for methods like `_.forIn` and `_.forOwn`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var index = -1, + iterable = Object(object), + props = keysFunc(object), + length = props.length; + + while (length--) { + var key = props[fromRight ? length : ++index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} + +module.exports = createBaseFor; + + +/***/ }), +/* 379 */ +/***/ (function(module, exports, __webpack_require__) { + +var isArrayLike = __webpack_require__(63); + +/** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + if (collection == null) { + return collection; + } + if (!isArrayLike(collection)) { + return eachFunc(collection, iteratee); + } + var length = collection.length, + index = fromRight ? length : -1, + iterable = Object(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; +} + +module.exports = createBaseEach; + + +/***/ }), +/* 380 */ +/***/ (function(module, exports, __webpack_require__) { + +var arrayEvery = __webpack_require__(381), + baseEvery = __webpack_require__(382), + baseIteratee = __webpack_require__(80), + isArray = __webpack_require__(17), + isIterateeCall = __webpack_require__(156); + +/** + * Checks if `predicate` returns truthy for **all** elements of `collection`. + * Iteration is stopped once `predicate` returns falsey. The predicate is + * invoked with three arguments: (value, index|key, collection). + * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': false }, + * { 'user': 'fred', 'age': 40, 'active': false } + * ]; + * + * // The `_.matches` iteratee shorthand. + * _.every(users, { 'user': 'barney', 'active': false }); + * // => false + * + * // The `_.matchesProperty` iteratee shorthand. + * _.every(users, ['active', false]); + * // => true + * + * // The `_.property` iteratee shorthand. + * _.every(users, 'active'); + * // => false + */ +function every(collection, predicate, guard) { + var func = isArray(collection) ? arrayEvery : baseEvery; + if (guard && isIterateeCall(collection, predicate, guard)) { + predicate = undefined; + } + return func(collection, baseIteratee(predicate, 3)); +} + +module.exports = every; + + +/***/ }), +/* 381 */ +/***/ (function(module, exports) { + +/** + * A specialized version of `_.every` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false`. + */ +function arrayEvery(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (!predicate(array[index], index, array)) { + return false; + } + } + return true; +} + +module.exports = arrayEvery; + + +/***/ }), +/* 382 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseEach = __webpack_require__(155); + +/** + * The base implementation of `_.every` without support for iteratee shorthands. + * + * @private + * @param {Array|Object} collection The collection to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if all elements pass the predicate check, + * else `false` + */ +function baseEvery(collection, predicate) { + var result = true; + baseEach(collection, function(value, index, collection) { + result = !!predicate(value, index, collection); + return result; + }); + return result; +} + +module.exports = baseEvery; + + +/***/ }), +/* 383 */ +/***/ (function(module, exports, __webpack_require__) { + +var createFind = __webpack_require__(384), + findIndex = __webpack_require__(385); + +/** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is invoked with three + * arguments: (value, index|key, collection). + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Collection + * @param {Array|Object} collection The collection to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.find(users, function(o) { return o.age < 40; }); + * // => object for 'barney' + * + * // The `_.matches` iteratee shorthand. + * _.find(users, { 'age': 1, 'active': true }); + * // => object for 'pebbles' + * + * // The `_.matchesProperty` iteratee shorthand. + * _.find(users, ['active', false]); + * // => object for 'fred' + * + * // The `_.property` iteratee shorthand. + * _.find(users, 'active'); + * // => object for 'barney' + */ +var find = createFind(findIndex); + +module.exports = find; + + +/***/ }), +/* 384 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIteratee = __webpack_require__(80), + isArrayLike = __webpack_require__(63), + keys = __webpack_require__(59); + +/** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} findIndexFunc The function to find the collection index. + * @returns {Function} Returns the new find function. + */ +function createFind(findIndexFunc) { + return function(collection, predicate, fromIndex) { + var iterable = Object(collection); + if (!isArrayLike(collection)) { + var iteratee = baseIteratee(predicate, 3); + collection = keys(collection); + predicate = function(key) { return iteratee(iterable[key], key, iterable); }; + } + var index = findIndexFunc(collection, predicate, fromIndex); + return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; + }; +} + +module.exports = createFind; + + +/***/ }), +/* 385 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseFindIndex = __webpack_require__(386), + baseIteratee = __webpack_require__(80), + toInteger = __webpack_require__(157); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * This method is like `_.find` except that it returns the index of the first + * element `predicate` returns truthy for instead of the element itself. + * + * @static + * @memberOf _ + * @since 1.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {Function} [predicate=_.identity] The function invoked per iteration. + * @param {number} [fromIndex=0] The index to search from. + * @returns {number} Returns the index of the found element, else `-1`. + * @example + * + * var users = [ + * { 'user': 'barney', 'active': false }, + * { 'user': 'fred', 'active': false }, + * { 'user': 'pebbles', 'active': true } + * ]; + * + * _.findIndex(users, function(o) { return o.user == 'barney'; }); + * // => 0 + * + * // The `_.matches` iteratee shorthand. + * _.findIndex(users, { 'user': 'fred', 'active': false }); + * // => 1 + * + * // The `_.matchesProperty` iteratee shorthand. + * _.findIndex(users, ['active', false]); + * // => 0 + * + * // The `_.property` iteratee shorthand. + * _.findIndex(users, 'active'); + * // => 2 + */ +function findIndex(array, predicate, fromIndex) { + var length = array == null ? 0 : array.length; + if (!length) { + return -1; + } + var index = fromIndex == null ? 0 : toInteger(fromIndex); + if (index < 0) { + index = nativeMax(length + index, 0); + } + return baseFindIndex(array, baseIteratee(predicate, 3), index); +} + +module.exports = findIndex; + + +/***/ }), +/* 386 */ +/***/ (function(module, exports) { + +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +module.exports = baseFindIndex; + + +/***/ }), +/* 387 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(64), + isSymbol = __webpack_require__(81); + +/** Used as references for various `Number` constants. */ +var NAN = 0 / 0; + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; + +/** Used to detect bad signed hexadecimal string values. */ +var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + +/** Used to detect binary string values. */ +var reIsBinary = /^0b[01]+$/i; + +/** Used to detect octal string values. */ +var reIsOctal = /^0o[0-7]+$/i; + +/** Built-in method references without a dependency on `root`. */ +var freeParseInt = parseInt; + +/** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ +function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); +} + +module.exports = toNumber; + + +/***/ }), +/* 388 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(process, global, setImmediate) {/* @preserve + * The MIT License (MIT) + * + * Copyright (c) 2013-2017 Petka Antonov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +/** + * bluebird build version 3.5.1 + * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each +*/ +!function(e){if(true)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;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 _dereq_=="function"&&_dereq_;for(var o=0;o 0) { + var fn = queue.shift(); + if (typeof fn !== "function") { + fn._settlePromises(); + continue; + } + var receiver = queue.shift(); + var arg = queue.shift(); + fn.call(receiver, arg); + } +}; + +Async.prototype._drainQueues = function () { + this._drainQueue(this._normalQueue); + this._reset(); + this._haveDrainedQueues = true; + this._drainQueue(this._lateQueue); +}; + +Async.prototype._queueTick = function () { + if (!this._isTickUsed) { + this._isTickUsed = true; + this._schedule(this.drainQueues); + } +}; + +Async.prototype._reset = function () { + this._isTickUsed = false; +}; + +module.exports = Async; +module.exports.firstLineError = firstLineError; + +},{"./queue":26,"./schedule":29,"./util":36}],3:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) { +var calledBind = false; +var rejectThis = function(_, e) { + this._reject(e); +}; + +var targetRejected = function(e, context) { + context.promiseRejectionQueued = true; + context.bindingPromise._then(rejectThis, rejectThis, null, this, e); +}; + +var bindingResolved = function(thisArg, context) { + if (((this._bitField & 50397184) === 0)) { + this._resolveCallback(context.target); + } +}; + +var bindingRejected = function(e, context) { + if (!context.promiseRejectionQueued) this._reject(e); +}; + +Promise.prototype.bind = function (thisArg) { + if (!calledBind) { + calledBind = true; + Promise.prototype._propagateFrom = debug.propagateFromFunction(); + Promise.prototype._boundValue = debug.boundValueFunction(); + } + var maybePromise = tryConvertToPromise(thisArg); + var ret = new Promise(INTERNAL); + ret._propagateFrom(this, 1); + var target = this._target(); + ret._setBoundTo(maybePromise); + if (maybePromise instanceof Promise) { + var context = { + promiseRejectionQueued: false, + promise: ret, + target: target, + bindingPromise: maybePromise + }; + target._then(INTERNAL, targetRejected, undefined, ret, context); + maybePromise._then( + bindingResolved, bindingRejected, undefined, ret, context); + ret._setOnCancel(maybePromise); + } else { + ret._resolveCallback(target); + } + return ret; +}; + +Promise.prototype._setBoundTo = function (obj) { + if (obj !== undefined) { + this._bitField = this._bitField | 2097152; + this._boundTo = obj; + } else { + this._bitField = this._bitField & (~2097152); + } +}; + +Promise.prototype._isBound = function () { + return (this._bitField & 2097152) === 2097152; +}; + +Promise.bind = function (thisArg, value) { + return Promise.resolve(value).bind(thisArg); +}; +}; + +},{}],4:[function(_dereq_,module,exports){ +"use strict"; +var old; +if (typeof Promise !== "undefined") old = Promise; +function noConflict() { + try { if (Promise === bluebird) Promise = old; } + catch (e) {} + return bluebird; +} +var bluebird = _dereq_("./promise")(); +bluebird.noConflict = noConflict; +module.exports = bluebird; + +},{"./promise":22}],5:[function(_dereq_,module,exports){ +"use strict"; +var cr = Object.create; +if (cr) { + var callerCache = cr(null); + var getterCache = cr(null); + callerCache[" size"] = getterCache[" size"] = 0; +} + +module.exports = function(Promise) { +var util = _dereq_("./util"); +var canEvaluate = util.canEvaluate; +var isIdentifier = util.isIdentifier; + +var getMethodCaller; +var getGetter; +if (false) { +var makeMethodCaller = function (methodName) { + return new Function("ensureMethod", " \n\ + return function(obj) { \n\ + 'use strict' \n\ + var len = this.length; \n\ + ensureMethod(obj, 'methodName'); \n\ + switch(len) { \n\ + case 1: return obj.methodName(this[0]); \n\ + case 2: return obj.methodName(this[0], this[1]); \n\ + case 3: return obj.methodName(this[0], this[1], this[2]); \n\ + case 0: return obj.methodName(); \n\ + default: \n\ + return obj.methodName.apply(obj, this); \n\ + } \n\ + }; \n\ + ".replace(/methodName/g, methodName))(ensureMethod); +}; + +var makeGetter = function (propertyName) { + return new Function("obj", " \n\ + 'use strict'; \n\ + return obj.propertyName; \n\ + ".replace("propertyName", propertyName)); +}; + +var getCompiled = function(name, compiler, cache) { + var ret = cache[name]; + if (typeof ret !== "function") { + if (!isIdentifier(name)) { + return null; + } + ret = compiler(name); + cache[name] = ret; + cache[" size"]++; + if (cache[" size"] > 512) { + var keys = Object.keys(cache); + for (var i = 0; i < 256; ++i) delete cache[keys[i]]; + cache[" size"] = keys.length - 256; + } + } + return ret; +}; + +getMethodCaller = function(name) { + return getCompiled(name, makeMethodCaller, callerCache); +}; + +getGetter = function(name) { + return getCompiled(name, makeGetter, getterCache); +}; +} + +function ensureMethod(obj, methodName) { + var fn; + if (obj != null) fn = obj[methodName]; + if (typeof fn !== "function") { + var message = "Object " + util.classString(obj) + " has no method '" + + util.toString(methodName) + "'"; + throw new Promise.TypeError(message); + } + return fn; +} + +function caller(obj) { + var methodName = this.pop(); + var fn = ensureMethod(obj, methodName); + return fn.apply(obj, this); +} +Promise.prototype.call = function (methodName) { + var args = [].slice.call(arguments, 1);; + if (false) { + if (canEvaluate) { + var maybeCaller = getMethodCaller(methodName); + if (maybeCaller !== null) { + return this._then( + maybeCaller, undefined, undefined, args, undefined); + } + } + } + args.push(methodName); + return this._then(caller, undefined, undefined, args, undefined); +}; + +function namedGetter(obj) { + return obj[this]; +} +function indexedGetter(obj) { + var index = +this; + if (index < 0) index = Math.max(0, index + obj.length); + return obj[index]; +} +Promise.prototype.get = function (propertyName) { + var isIndex = (typeof propertyName === "number"); + var getter; + if (!isIndex) { + if (canEvaluate) { + var maybeGetter = getGetter(propertyName); + getter = maybeGetter !== null ? maybeGetter : namedGetter; + } else { + getter = namedGetter; + } + } else { + getter = indexedGetter; + } + return this._then(getter, undefined, undefined, propertyName, undefined); +}; +}; + +},{"./util":36}],6:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, PromiseArray, apiRejection, debug) { +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var async = Promise._async; + +Promise.prototype["break"] = Promise.prototype.cancel = function() { + if (!debug.cancellation()) return this._warn("cancellation is disabled"); + + var promise = this; + var child = promise; + while (promise._isCancellable()) { + if (!promise._cancelBy(child)) { + if (child._isFollowing()) { + child._followee().cancel(); + } else { + child._cancelBranched(); + } + break; + } + + var parent = promise._cancellationParent; + if (parent == null || !parent._isCancellable()) { + if (promise._isFollowing()) { + promise._followee().cancel(); + } else { + promise._cancelBranched(); + } + break; + } else { + if (promise._isFollowing()) promise._followee().cancel(); + promise._setWillBeCancelled(); + child = promise; + promise = parent; + } + } +}; + +Promise.prototype._branchHasCancelled = function() { + this._branchesRemainingToCancel--; +}; + +Promise.prototype._enoughBranchesHaveCancelled = function() { + return this._branchesRemainingToCancel === undefined || + this._branchesRemainingToCancel <= 0; +}; + +Promise.prototype._cancelBy = function(canceller) { + if (canceller === this) { + this._branchesRemainingToCancel = 0; + this._invokeOnCancel(); + return true; + } else { + this._branchHasCancelled(); + if (this._enoughBranchesHaveCancelled()) { + this._invokeOnCancel(); + return true; + } + } + return false; +}; + +Promise.prototype._cancelBranched = function() { + if (this._enoughBranchesHaveCancelled()) { + this._cancel(); + } +}; + +Promise.prototype._cancel = function() { + if (!this._isCancellable()) return; + this._setCancelled(); + async.invoke(this._cancelPromises, this, undefined); +}; + +Promise.prototype._cancelPromises = function() { + if (this._length() > 0) this._settlePromises(); +}; + +Promise.prototype._unsetOnCancel = function() { + this._onCancelField = undefined; +}; + +Promise.prototype._isCancellable = function() { + return this.isPending() && !this._isCancelled(); +}; + +Promise.prototype.isCancellable = function() { + return this.isPending() && !this.isCancelled(); +}; + +Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) { + if (util.isArray(onCancelCallback)) { + for (var i = 0; i < onCancelCallback.length; ++i) { + this._doInvokeOnCancel(onCancelCallback[i], internalOnly); + } + } else if (onCancelCallback !== undefined) { + if (typeof onCancelCallback === "function") { + if (!internalOnly) { + var e = tryCatch(onCancelCallback).call(this._boundValue()); + if (e === errorObj) { + this._attachExtraTrace(e.e); + async.throwLater(e.e); + } + } + } else { + onCancelCallback._resultCancelled(this); + } + } +}; + +Promise.prototype._invokeOnCancel = function() { + var onCancelCallback = this._onCancel(); + this._unsetOnCancel(); + async.invoke(this._doInvokeOnCancel, this, onCancelCallback); +}; + +Promise.prototype._invokeInternalOnCancel = function() { + if (this._isCancellable()) { + this._doInvokeOnCancel(this._onCancel(), true); + this._unsetOnCancel(); + } +}; + +Promise.prototype._resultCancelled = function() { + this.cancel(); +}; + +}; + +},{"./util":36}],7:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(NEXT_FILTER) { +var util = _dereq_("./util"); +var getKeys = _dereq_("./es5").keys; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +function catchFilter(instances, cb, promise) { + return function(e) { + var boundTo = promise._boundValue(); + predicateLoop: for (var i = 0; i < instances.length; ++i) { + var item = instances[i]; + + if (item === Error || + (item != null && item.prototype instanceof Error)) { + if (e instanceof item) { + return tryCatch(cb).call(boundTo, e); + } + } else if (typeof item === "function") { + var matchesPredicate = tryCatch(item).call(boundTo, e); + if (matchesPredicate === errorObj) { + return matchesPredicate; + } else if (matchesPredicate) { + return tryCatch(cb).call(boundTo, e); + } + } else if (util.isObject(e)) { + var keys = getKeys(item); + for (var j = 0; j < keys.length; ++j) { + var key = keys[j]; + if (item[key] != e[key]) { + continue predicateLoop; + } + } + return tryCatch(cb).call(boundTo, e); + } + } + return NEXT_FILTER; + }; +} + +return catchFilter; +}; + +},{"./es5":13,"./util":36}],8:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +var longStackTraces = false; +var contextStack = []; + +Promise.prototype._promiseCreated = function() {}; +Promise.prototype._pushContext = function() {}; +Promise.prototype._popContext = function() {return null;}; +Promise._peekContext = Promise.prototype._peekContext = function() {}; + +function Context() { + this._trace = new Context.CapturedTrace(peekContext()); +} +Context.prototype._pushContext = function () { + if (this._trace !== undefined) { + this._trace._promiseCreated = null; + contextStack.push(this._trace); + } +}; + +Context.prototype._popContext = function () { + if (this._trace !== undefined) { + var trace = contextStack.pop(); + var ret = trace._promiseCreated; + trace._promiseCreated = null; + return ret; + } + return null; +}; + +function createContext() { + if (longStackTraces) return new Context(); +} + +function peekContext() { + var lastIndex = contextStack.length - 1; + if (lastIndex >= 0) { + return contextStack[lastIndex]; + } + return undefined; +} +Context.CapturedTrace = null; +Context.create = createContext; +Context.deactivateLongStackTraces = function() {}; +Context.activateLongStackTraces = function() { + var Promise_pushContext = Promise.prototype._pushContext; + var Promise_popContext = Promise.prototype._popContext; + var Promise_PeekContext = Promise._peekContext; + var Promise_peekContext = Promise.prototype._peekContext; + var Promise_promiseCreated = Promise.prototype._promiseCreated; + Context.deactivateLongStackTraces = function() { + Promise.prototype._pushContext = Promise_pushContext; + Promise.prototype._popContext = Promise_popContext; + Promise._peekContext = Promise_PeekContext; + Promise.prototype._peekContext = Promise_peekContext; + Promise.prototype._promiseCreated = Promise_promiseCreated; + longStackTraces = false; + }; + longStackTraces = true; + Promise.prototype._pushContext = Context.prototype._pushContext; + Promise.prototype._popContext = Context.prototype._popContext; + Promise._peekContext = Promise.prototype._peekContext = peekContext; + Promise.prototype._promiseCreated = function() { + var ctx = this._peekContext(); + if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this; + }; +}; +return Context; +}; + +},{}],9:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, Context) { +var getDomain = Promise._getDomain; +var async = Promise._async; +var Warning = _dereq_("./errors").Warning; +var util = _dereq_("./util"); +var canAttachTrace = util.canAttachTrace; +var unhandledRejectionHandled; +var possiblyUnhandledRejection; +var bluebirdFramePattern = + /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/; +var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/; +var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/; +var stackFramePattern = null; +var formatStack = null; +var indentStackFrames = false; +var printWarning; +var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 && + (true || + util.env("BLUEBIRD_DEBUG") || + util.env("NODE_ENV") === "development")); + +var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 && + (debugging || util.env("BLUEBIRD_WARNINGS"))); + +var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 && + (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES"))); + +var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 && + (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN")); + +Promise.prototype.suppressUnhandledRejections = function() { + var target = this._target(); + target._bitField = ((target._bitField & (~1048576)) | + 524288); +}; + +Promise.prototype._ensurePossibleRejectionHandled = function () { + if ((this._bitField & 524288) !== 0) return; + this._setRejectionIsUnhandled(); + var self = this; + setTimeout(function() { + self._notifyUnhandledRejection(); + }, 1); +}; + +Promise.prototype._notifyUnhandledRejectionIsHandled = function () { + fireRejectionEvent("rejectionHandled", + unhandledRejectionHandled, undefined, this); +}; + +Promise.prototype._setReturnedNonUndefined = function() { + this._bitField = this._bitField | 268435456; +}; + +Promise.prototype._returnedNonUndefined = function() { + return (this._bitField & 268435456) !== 0; +}; + +Promise.prototype._notifyUnhandledRejection = function () { + if (this._isRejectionUnhandled()) { + var reason = this._settledValue(); + this._setUnhandledRejectionIsNotified(); + fireRejectionEvent("unhandledRejection", + possiblyUnhandledRejection, reason, this); + } +}; + +Promise.prototype._setUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField | 262144; +}; + +Promise.prototype._unsetUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField & (~262144); +}; + +Promise.prototype._isUnhandledRejectionNotified = function () { + return (this._bitField & 262144) > 0; +}; + +Promise.prototype._setRejectionIsUnhandled = function () { + this._bitField = this._bitField | 1048576; +}; + +Promise.prototype._unsetRejectionIsUnhandled = function () { + this._bitField = this._bitField & (~1048576); + if (this._isUnhandledRejectionNotified()) { + this._unsetUnhandledRejectionIsNotified(); + this._notifyUnhandledRejectionIsHandled(); + } +}; + +Promise.prototype._isRejectionUnhandled = function () { + return (this._bitField & 1048576) > 0; +}; + +Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) { + return warn(message, shouldUseOwnTrace, promise || this); +}; + +Promise.onPossiblyUnhandledRejection = function (fn) { + var domain = getDomain(); + possiblyUnhandledRejection = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; +}; + +Promise.onUnhandledRejectionHandled = function (fn) { + var domain = getDomain(); + unhandledRejectionHandled = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; +}; + +var disableLongStackTraces = function() {}; +Promise.longStackTraces = function () { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (!config.longStackTraces && longStackTracesIsSupported()) { + var Promise_captureStackTrace = Promise.prototype._captureStackTrace; + var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace; + config.longStackTraces = true; + disableLongStackTraces = function() { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + Promise.prototype._captureStackTrace = Promise_captureStackTrace; + Promise.prototype._attachExtraTrace = Promise_attachExtraTrace; + Context.deactivateLongStackTraces(); + async.enableTrampoline(); + config.longStackTraces = false; + }; + Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace; + Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace; + Context.activateLongStackTraces(); + async.disableTrampolineIfNecessary(); + } +}; + +Promise.hasLongStackTraces = function () { + return config.longStackTraces && longStackTracesIsSupported(); +}; + +var fireDomEvent = (function() { + try { + if (typeof CustomEvent === "function") { + var event = new CustomEvent("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = new CustomEvent(name.toLowerCase(), { + detail: event, + cancelable: true + }); + return !util.global.dispatchEvent(domEvent); + }; + } else if (typeof Event === "function") { + var event = new Event("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = new Event(name.toLowerCase(), { + cancelable: true + }); + domEvent.detail = event; + return !util.global.dispatchEvent(domEvent); + }; + } else { + var event = document.createEvent("CustomEvent"); + event.initCustomEvent("testingtheevent", false, true, {}); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = document.createEvent("CustomEvent"); + domEvent.initCustomEvent(name.toLowerCase(), false, true, + event); + return !util.global.dispatchEvent(domEvent); + }; + } + } catch (e) {} + return function() { + return false; + }; +})(); + +var fireGlobalEvent = (function() { + if (util.isNode) { + return function() { + return process.emit.apply(process, arguments); + }; + } else { + if (!util.global) { + return function() { + return false; + }; + } + return function(name) { + var methodName = "on" + name.toLowerCase(); + var method = util.global[methodName]; + if (!method) return false; + method.apply(util.global, [].slice.call(arguments, 1)); + return true; + }; + } +})(); + +function generatePromiseLifecycleEventObject(name, promise) { + return {promise: promise}; +} + +var eventToObjectGenerator = { + promiseCreated: generatePromiseLifecycleEventObject, + promiseFulfilled: generatePromiseLifecycleEventObject, + promiseRejected: generatePromiseLifecycleEventObject, + promiseResolved: generatePromiseLifecycleEventObject, + promiseCancelled: generatePromiseLifecycleEventObject, + promiseChained: function(name, promise, child) { + return {promise: promise, child: child}; + }, + warning: function(name, warning) { + return {warning: warning}; + }, + unhandledRejection: function (name, reason, promise) { + return {reason: reason, promise: promise}; + }, + rejectionHandled: generatePromiseLifecycleEventObject +}; + +var activeFireEvent = function (name) { + var globalEventFired = false; + try { + globalEventFired = fireGlobalEvent.apply(null, arguments); + } catch (e) { + async.throwLater(e); + globalEventFired = true; + } + + var domEventFired = false; + try { + domEventFired = fireDomEvent(name, + eventToObjectGenerator[name].apply(null, arguments)); + } catch (e) { + async.throwLater(e); + domEventFired = true; + } + + return domEventFired || globalEventFired; +}; + +Promise.config = function(opts) { + opts = Object(opts); + if ("longStackTraces" in opts) { + if (opts.longStackTraces) { + Promise.longStackTraces(); + } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) { + disableLongStackTraces(); + } + } + if ("warnings" in opts) { + var warningsOption = opts.warnings; + config.warnings = !!warningsOption; + wForgottenReturn = config.warnings; + + if (util.isObject(warningsOption)) { + if ("wForgottenReturn" in warningsOption) { + wForgottenReturn = !!warningsOption.wForgottenReturn; + } + } + } + if ("cancellation" in opts && opts.cancellation && !config.cancellation) { + if (async.haveItemsQueued()) { + throw new Error( + "cannot enable cancellation after promises are in use"); + } + Promise.prototype._clearCancellationData = + cancellationClearCancellationData; + Promise.prototype._propagateFrom = cancellationPropagateFrom; + Promise.prototype._onCancel = cancellationOnCancel; + Promise.prototype._setOnCancel = cancellationSetOnCancel; + Promise.prototype._attachCancellationCallback = + cancellationAttachCancellationCallback; + Promise.prototype._execute = cancellationExecute; + propagateFromFunction = cancellationPropagateFrom; + config.cancellation = true; + } + if ("monitoring" in opts) { + if (opts.monitoring && !config.monitoring) { + config.monitoring = true; + Promise.prototype._fireEvent = activeFireEvent; + } else if (!opts.monitoring && config.monitoring) { + config.monitoring = false; + Promise.prototype._fireEvent = defaultFireEvent; + } + } + return Promise; +}; + +function defaultFireEvent() { return false; } + +Promise.prototype._fireEvent = defaultFireEvent; +Promise.prototype._execute = function(executor, resolve, reject) { + try { + executor(resolve, reject); + } catch (e) { + return e; + } +}; +Promise.prototype._onCancel = function () {}; +Promise.prototype._setOnCancel = function (handler) { ; }; +Promise.prototype._attachCancellationCallback = function(onCancel) { + ; +}; +Promise.prototype._captureStackTrace = function () {}; +Promise.prototype._attachExtraTrace = function () {}; +Promise.prototype._clearCancellationData = function() {}; +Promise.prototype._propagateFrom = function (parent, flags) { + ; + ; +}; + +function cancellationExecute(executor, resolve, reject) { + var promise = this; + try { + executor(resolve, reject, function(onCancel) { + if (typeof onCancel !== "function") { + throw new TypeError("onCancel must be a function, got: " + + util.toString(onCancel)); + } + promise._attachCancellationCallback(onCancel); + }); + } catch (e) { + return e; + } +} + +function cancellationAttachCancellationCallback(onCancel) { + if (!this._isCancellable()) return this; + + var previousOnCancel = this._onCancel(); + if (previousOnCancel !== undefined) { + if (util.isArray(previousOnCancel)) { + previousOnCancel.push(onCancel); + } else { + this._setOnCancel([previousOnCancel, onCancel]); + } + } else { + this._setOnCancel(onCancel); + } +} + +function cancellationOnCancel() { + return this._onCancelField; +} + +function cancellationSetOnCancel(onCancel) { + this._onCancelField = onCancel; +} + +function cancellationClearCancellationData() { + this._cancellationParent = undefined; + this._onCancelField = undefined; +} + +function cancellationPropagateFrom(parent, flags) { + if ((flags & 1) !== 0) { + this._cancellationParent = parent; + var branchesRemainingToCancel = parent._branchesRemainingToCancel; + if (branchesRemainingToCancel === undefined) { + branchesRemainingToCancel = 0; + } + parent._branchesRemainingToCancel = branchesRemainingToCancel + 1; + } + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } +} + +function bindingPropagateFrom(parent, flags) { + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } +} +var propagateFromFunction = bindingPropagateFrom; + +function boundValueFunction() { + var ret = this._boundTo; + if (ret !== undefined) { + if (ret instanceof Promise) { + if (ret.isFulfilled()) { + return ret.value(); + } else { + return undefined; + } + } + } + return ret; +} + +function longStackTracesCaptureStackTrace() { + this._trace = new CapturedTrace(this._peekContext()); +} + +function longStackTracesAttachExtraTrace(error, ignoreSelf) { + if (canAttachTrace(error)) { + var trace = this._trace; + if (trace !== undefined) { + if (ignoreSelf) trace = trace._parent; + } + if (trace !== undefined) { + trace.attachExtraTrace(error); + } else if (!error.__stackCleaned__) { + var parsed = parseStackAndMessage(error); + util.notEnumerableProp(error, "stack", + parsed.message + "\n" + parsed.stack.join("\n")); + util.notEnumerableProp(error, "__stackCleaned__", true); + } + } +} + +function checkForgottenReturns(returnValue, promiseCreated, name, promise, + parent) { + if (returnValue === undefined && promiseCreated !== null && + wForgottenReturn) { + if (parent !== undefined && parent._returnedNonUndefined()) return; + if ((promise._bitField & 65535) === 0) return; + + if (name) name = name + " "; + var handlerLine = ""; + var creatorLine = ""; + if (promiseCreated._trace) { + var traceLines = promiseCreated._trace.stack.split("\n"); + var stack = cleanStack(traceLines); + for (var i = stack.length - 1; i >= 0; --i) { + var line = stack[i]; + if (!nodeFramePattern.test(line)) { + var lineMatches = line.match(parseLinePattern); + if (lineMatches) { + handlerLine = "at " + lineMatches[1] + + ":" + lineMatches[2] + ":" + lineMatches[3] + " "; + } + break; + } + } + + if (stack.length > 0) { + var firstUserLine = stack[0]; + for (var i = 0; i < traceLines.length; ++i) { + + if (traceLines[i] === firstUserLine) { + if (i > 0) { + creatorLine = "\n" + traceLines[i - 1]; + } + break; + } + } + + } + } + var msg = "a promise was created in a " + name + + "handler " + handlerLine + "but was not returned from it, " + + "see http://goo.gl/rRqMUw" + + creatorLine; + promise._warn(msg, true, promiseCreated); + } +} + +function deprecated(name, replacement) { + var message = name + + " is deprecated and will be removed in a future version."; + if (replacement) message += " Use " + replacement + " instead."; + return warn(message); +} + +function warn(message, shouldUseOwnTrace, promise) { + if (!config.warnings) return; + var warning = new Warning(message); + var ctx; + if (shouldUseOwnTrace) { + promise._attachExtraTrace(warning); + } else if (config.longStackTraces && (ctx = Promise._peekContext())) { + ctx.attachExtraTrace(warning); + } else { + var parsed = parseStackAndMessage(warning); + warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); + } + + if (!activeFireEvent("warning", warning)) { + formatAndLogError(warning, "", true); + } +} + +function reconstructStack(message, stacks) { + for (var i = 0; i < stacks.length - 1; ++i) { + stacks[i].push("From previous event:"); + stacks[i] = stacks[i].join("\n"); + } + if (i < stacks.length) { + stacks[i] = stacks[i].join("\n"); + } + return message + "\n" + stacks.join("\n"); +} + +function removeDuplicateOrEmptyJumps(stacks) { + for (var i = 0; i < stacks.length; ++i) { + if (stacks[i].length === 0 || + ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { + stacks.splice(i, 1); + i--; + } + } +} + +function removeCommonRoots(stacks) { + var current = stacks[0]; + for (var i = 1; i < stacks.length; ++i) { + var prev = stacks[i]; + var currentLastIndex = current.length - 1; + var currentLastLine = current[currentLastIndex]; + var commonRootMeetPoint = -1; + + for (var j = prev.length - 1; j >= 0; --j) { + if (prev[j] === currentLastLine) { + commonRootMeetPoint = j; + break; + } + } + + for (var j = commonRootMeetPoint; j >= 0; --j) { + var line = prev[j]; + if (current[currentLastIndex] === line) { + current.pop(); + currentLastIndex--; + } else { + break; + } + } + current = prev; + } +} + +function cleanStack(stack) { + var ret = []; + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + var isTraceLine = " (No stack trace)" === line || + stackFramePattern.test(line); + var isInternalFrame = isTraceLine && shouldIgnore(line); + if (isTraceLine && !isInternalFrame) { + if (indentStackFrames && line.charAt(0) !== " ") { + line = " " + line; + } + ret.push(line); + } + } + return ret; +} + +function stackFramesAsArray(error) { + var stack = error.stack.replace(/\s+$/g, "").split("\n"); + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + if (" (No stack trace)" === line || stackFramePattern.test(line)) { + break; + } + } + if (i > 0 && error.name != "SyntaxError") { + stack = stack.slice(i); + } + return stack; +} + +function parseStackAndMessage(error) { + var stack = error.stack; + var message = error.toString(); + stack = typeof stack === "string" && stack.length > 0 + ? stackFramesAsArray(error) : [" (No stack trace)"]; + return { + message: message, + stack: error.name == "SyntaxError" ? stack : cleanStack(stack) + }; +} + +function formatAndLogError(error, title, isSoft) { + if (typeof console !== "undefined") { + var message; + if (util.isObject(error)) { + var stack = error.stack; + message = title + formatStack(stack, error); + } else { + message = title + String(error); + } + if (typeof printWarning === "function") { + printWarning(message, isSoft); + } else if (typeof console.log === "function" || + typeof console.log === "object") { + console.log(message); + } + } +} + +function fireRejectionEvent(name, localHandler, reason, promise) { + var localEventFired = false; + try { + if (typeof localHandler === "function") { + localEventFired = true; + if (name === "rejectionHandled") { + localHandler(promise); + } else { + localHandler(reason, promise); + } + } + } catch (e) { + async.throwLater(e); + } + + if (name === "unhandledRejection") { + if (!activeFireEvent(name, reason, promise) && !localEventFired) { + formatAndLogError(reason, "Unhandled rejection "); + } + } else { + activeFireEvent(name, promise); + } +} + +function formatNonError(obj) { + var str; + if (typeof obj === "function") { + str = "[function " + + (obj.name || "anonymous") + + "]"; + } else { + str = obj && typeof obj.toString === "function" + ? obj.toString() : util.toString(obj); + var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/; + if (ruselessToString.test(str)) { + try { + var newStr = JSON.stringify(obj); + str = newStr; + } + catch(e) { + + } + } + if (str.length === 0) { + str = "(empty array)"; + } + } + return ("(<" + snip(str) + ">, no stack trace)"); +} + +function snip(str) { + var maxChars = 41; + if (str.length < maxChars) { + return str; + } + return str.substr(0, maxChars - 3) + "..."; +} + +function longStackTracesIsSupported() { + return typeof captureStackTrace === "function"; +} + +var shouldIgnore = function() { return false; }; +var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; +function parseLineInfo(line) { + var matches = line.match(parseLineInfoRegex); + if (matches) { + return { + fileName: matches[1], + line: parseInt(matches[2], 10) + }; + } +} + +function setBounds(firstLineError, lastLineError) { + if (!longStackTracesIsSupported()) return; + var firstStackLines = firstLineError.stack.split("\n"); + var lastStackLines = lastLineError.stack.split("\n"); + var firstIndex = -1; + var lastIndex = -1; + var firstFileName; + var lastFileName; + for (var i = 0; i < firstStackLines.length; ++i) { + var result = parseLineInfo(firstStackLines[i]); + if (result) { + firstFileName = result.fileName; + firstIndex = result.line; + break; + } + } + for (var i = 0; i < lastStackLines.length; ++i) { + var result = parseLineInfo(lastStackLines[i]); + if (result) { + lastFileName = result.fileName; + lastIndex = result.line; + break; + } + } + if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || + firstFileName !== lastFileName || firstIndex >= lastIndex) { + return; + } + + shouldIgnore = function(line) { + if (bluebirdFramePattern.test(line)) return true; + var info = parseLineInfo(line); + if (info) { + if (info.fileName === firstFileName && + (firstIndex <= info.line && info.line <= lastIndex)) { + return true; + } + } + return false; + }; +} + +function CapturedTrace(parent) { + this._parent = parent; + this._promisesCreated = 0; + var length = this._length = 1 + (parent === undefined ? 0 : parent._length); + captureStackTrace(this, CapturedTrace); + if (length > 32) this.uncycle(); +} +util.inherits(CapturedTrace, Error); +Context.CapturedTrace = CapturedTrace; + +CapturedTrace.prototype.uncycle = function() { + var length = this._length; + if (length < 2) return; + var nodes = []; + var stackToIndex = {}; + + for (var i = 0, node = this; node !== undefined; ++i) { + nodes.push(node); + node = node._parent; + } + length = this._length = i; + for (var i = length - 1; i >= 0; --i) { + var stack = nodes[i].stack; + if (stackToIndex[stack] === undefined) { + stackToIndex[stack] = i; + } + } + for (var i = 0; i < length; ++i) { + var currentStack = nodes[i].stack; + var index = stackToIndex[currentStack]; + if (index !== undefined && index !== i) { + if (index > 0) { + nodes[index - 1]._parent = undefined; + nodes[index - 1]._length = 1; + } + nodes[i]._parent = undefined; + nodes[i]._length = 1; + var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; + + if (index < length - 1) { + cycleEdgeNode._parent = nodes[index + 1]; + cycleEdgeNode._parent.uncycle(); + cycleEdgeNode._length = + cycleEdgeNode._parent._length + 1; + } else { + cycleEdgeNode._parent = undefined; + cycleEdgeNode._length = 1; + } + var currentChildLength = cycleEdgeNode._length + 1; + for (var j = i - 2; j >= 0; --j) { + nodes[j]._length = currentChildLength; + currentChildLength++; + } + return; + } + } +}; + +CapturedTrace.prototype.attachExtraTrace = function(error) { + if (error.__stackCleaned__) return; + this.uncycle(); + var parsed = parseStackAndMessage(error); + var message = parsed.message; + var stacks = [parsed.stack]; + + var trace = this; + while (trace !== undefined) { + stacks.push(cleanStack(trace.stack.split("\n"))); + trace = trace._parent; + } + removeCommonRoots(stacks); + removeDuplicateOrEmptyJumps(stacks); + util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); + util.notEnumerableProp(error, "__stackCleaned__", true); +}; + +var captureStackTrace = (function stackDetection() { + var v8stackFramePattern = /^\s*at\s*/; + var v8stackFormatter = function(stack, error) { + if (typeof stack === "string") return stack; + + if (error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + if (typeof Error.stackTraceLimit === "number" && + typeof Error.captureStackTrace === "function") { + Error.stackTraceLimit += 6; + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + var captureStackTrace = Error.captureStackTrace; + + shouldIgnore = function(line) { + return bluebirdFramePattern.test(line); + }; + return function(receiver, ignoreUntil) { + Error.stackTraceLimit += 6; + captureStackTrace(receiver, ignoreUntil); + Error.stackTraceLimit -= 6; + }; + } + var err = new Error(); + + if (typeof err.stack === "string" && + err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { + stackFramePattern = /@/; + formatStack = v8stackFormatter; + indentStackFrames = true; + return function captureStackTrace(o) { + o.stack = new Error().stack; + }; + } + + var hasStackAfterThrow; + try { throw new Error(); } + catch(e) { + hasStackAfterThrow = ("stack" in e); + } + if (!("stack" in err) && hasStackAfterThrow && + typeof Error.stackTraceLimit === "number") { + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + return function captureStackTrace(o) { + Error.stackTraceLimit += 6; + try { throw new Error(); } + catch(e) { o.stack = e.stack; } + Error.stackTraceLimit -= 6; + }; + } + + formatStack = function(stack, error) { + if (typeof stack === "string") return stack; + + if ((typeof error === "object" || + typeof error === "function") && + error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + return null; + +})([]); + +if (typeof console !== "undefined" && typeof console.warn !== "undefined") { + printWarning = function (message) { + console.warn(message); + }; + if (util.isNode && process.stderr.isTTY) { + printWarning = function(message, isSoft) { + var color = isSoft ? "\u001b[33m" : "\u001b[31m"; + console.warn(color + message + "\u001b[0m\n"); + }; + } else if (!util.isNode && typeof (new Error().stack) === "string") { + printWarning = function(message, isSoft) { + console.warn("%c" + message, + isSoft ? "color: darkorange" : "color: red"); + }; + } +} + +var config = { + warnings: warnings, + longStackTraces: false, + cancellation: false, + monitoring: false +}; + +if (longStackTraces) Promise.longStackTraces(); + +return { + longStackTraces: function() { + return config.longStackTraces; + }, + warnings: function() { + return config.warnings; + }, + cancellation: function() { + return config.cancellation; + }, + monitoring: function() { + return config.monitoring; + }, + propagateFromFunction: function() { + return propagateFromFunction; + }, + boundValueFunction: function() { + return boundValueFunction; + }, + checkForgottenReturns: checkForgottenReturns, + setBounds: setBounds, + warn: warn, + deprecated: deprecated, + CapturedTrace: CapturedTrace, + fireDomEvent: fireDomEvent, + fireGlobalEvent: fireGlobalEvent +}; +}; + +},{"./errors":12,"./util":36}],10:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +function returner() { + return this.value; +} +function thrower() { + throw this.reason; +} + +Promise.prototype["return"] = +Promise.prototype.thenReturn = function (value) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + returner, undefined, undefined, {value: value}, undefined); +}; + +Promise.prototype["throw"] = +Promise.prototype.thenThrow = function (reason) { + return this._then( + thrower, undefined, undefined, {reason: reason}, undefined); +}; + +Promise.prototype.catchThrow = function (reason) { + if (arguments.length <= 1) { + return this._then( + undefined, thrower, undefined, {reason: reason}, undefined); + } else { + var _reason = arguments[1]; + var handler = function() {throw _reason;}; + return this.caught(reason, handler); + } +}; + +Promise.prototype.catchReturn = function (value) { + if (arguments.length <= 1) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + undefined, returner, undefined, {value: value}, undefined); + } else { + var _value = arguments[1]; + if (_value instanceof Promise) _value.suppressUnhandledRejections(); + var handler = function() {return _value;}; + return this.caught(value, handler); + } +}; +}; + +},{}],11:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var PromiseReduce = Promise.reduce; +var PromiseAll = Promise.all; + +function promiseAllThis() { + return PromiseAll(this); +} + +function PromiseMapSeries(promises, fn) { + return PromiseReduce(promises, fn, INTERNAL, INTERNAL); +} + +Promise.prototype.each = function (fn) { + return PromiseReduce(this, fn, INTERNAL, 0) + ._then(promiseAllThis, undefined, undefined, this, undefined); +}; + +Promise.prototype.mapSeries = function (fn) { + return PromiseReduce(this, fn, INTERNAL, INTERNAL); +}; + +Promise.each = function (promises, fn) { + return PromiseReduce(promises, fn, INTERNAL, 0) + ._then(promiseAllThis, undefined, undefined, promises, undefined); +}; + +Promise.mapSeries = PromiseMapSeries; +}; + + +},{}],12:[function(_dereq_,module,exports){ +"use strict"; +var es5 = _dereq_("./es5"); +var Objectfreeze = es5.freeze; +var util = _dereq_("./util"); +var inherits = util.inherits; +var notEnumerableProp = util.notEnumerableProp; + +function subError(nameProperty, defaultMessage) { + function SubError(message) { + if (!(this instanceof SubError)) return new SubError(message); + notEnumerableProp(this, "message", + typeof message === "string" ? message : defaultMessage); + notEnumerableProp(this, "name", nameProperty); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } else { + Error.call(this); + } + } + inherits(SubError, Error); + return SubError; +} + +var _TypeError, _RangeError; +var Warning = subError("Warning", "warning"); +var CancellationError = subError("CancellationError", "cancellation error"); +var TimeoutError = subError("TimeoutError", "timeout error"); +var AggregateError = subError("AggregateError", "aggregate error"); +try { + _TypeError = TypeError; + _RangeError = RangeError; +} catch(e) { + _TypeError = subError("TypeError", "type error"); + _RangeError = subError("RangeError", "range error"); +} + +var methods = ("join pop push shift unshift slice filter forEach some " + + "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" "); + +for (var i = 0; i < methods.length; ++i) { + if (typeof Array.prototype[methods[i]] === "function") { + AggregateError.prototype[methods[i]] = Array.prototype[methods[i]]; + } +} + +es5.defineProperty(AggregateError.prototype, "length", { + value: 0, + configurable: false, + writable: true, + enumerable: true +}); +AggregateError.prototype["isOperational"] = true; +var level = 0; +AggregateError.prototype.toString = function() { + var indent = Array(level * 4 + 1).join(" "); + var ret = "\n" + indent + "AggregateError of:" + "\n"; + level++; + indent = Array(level * 4 + 1).join(" "); + for (var i = 0; i < this.length; ++i) { + var str = this[i] === this ? "[Circular AggregateError]" : this[i] + ""; + var lines = str.split("\n"); + for (var j = 0; j < lines.length; ++j) { + lines[j] = indent + lines[j]; + } + str = lines.join("\n"); + ret += str + "\n"; + } + level--; + return ret; +}; + +function OperationalError(message) { + if (!(this instanceof OperationalError)) + return new OperationalError(message); + notEnumerableProp(this, "name", "OperationalError"); + notEnumerableProp(this, "message", message); + this.cause = message; + this["isOperational"] = true; + + if (message instanceof Error) { + notEnumerableProp(this, "message", message.message); + notEnumerableProp(this, "stack", message.stack); + } else if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + +} +inherits(OperationalError, Error); + +var errorTypes = Error["__BluebirdErrorTypes__"]; +if (!errorTypes) { + errorTypes = Objectfreeze({ + CancellationError: CancellationError, + TimeoutError: TimeoutError, + OperationalError: OperationalError, + RejectionError: OperationalError, + AggregateError: AggregateError + }); + es5.defineProperty(Error, "__BluebirdErrorTypes__", { + value: errorTypes, + writable: false, + enumerable: false, + configurable: false + }); +} + +module.exports = { + Error: Error, + TypeError: _TypeError, + RangeError: _RangeError, + CancellationError: errorTypes.CancellationError, + OperationalError: errorTypes.OperationalError, + TimeoutError: errorTypes.TimeoutError, + AggregateError: errorTypes.AggregateError, + Warning: Warning +}; + +},{"./es5":13,"./util":36}],13:[function(_dereq_,module,exports){ +var isES5 = (function(){ + "use strict"; + return this === undefined; +})(); + +if (isES5) { + module.exports = { + freeze: Object.freeze, + defineProperty: Object.defineProperty, + getDescriptor: Object.getOwnPropertyDescriptor, + keys: Object.keys, + names: Object.getOwnPropertyNames, + getPrototypeOf: Object.getPrototypeOf, + isArray: Array.isArray, + isES5: isES5, + propertyIsWritable: function(obj, prop) { + var descriptor = Object.getOwnPropertyDescriptor(obj, prop); + return !!(!descriptor || descriptor.writable || descriptor.set); + } + }; +} else { + var has = {}.hasOwnProperty; + var str = {}.toString; + var proto = {}.constructor.prototype; + + var ObjectKeys = function (o) { + var ret = []; + for (var key in o) { + if (has.call(o, key)) { + ret.push(key); + } + } + return ret; + }; + + var ObjectGetDescriptor = function(o, key) { + return {value: o[key]}; + }; + + var ObjectDefineProperty = function (o, key, desc) { + o[key] = desc.value; + return o; + }; + + var ObjectFreeze = function (obj) { + return obj; + }; + + var ObjectGetPrototypeOf = function (obj) { + try { + return Object(obj).constructor.prototype; + } + catch (e) { + return proto; + } + }; + + var ArrayIsArray = function (obj) { + try { + return str.call(obj) === "[object Array]"; + } + catch(e) { + return false; + } + }; + + module.exports = { + isArray: ArrayIsArray, + keys: ObjectKeys, + names: ObjectKeys, + defineProperty: ObjectDefineProperty, + getDescriptor: ObjectGetDescriptor, + freeze: ObjectFreeze, + getPrototypeOf: ObjectGetPrototypeOf, + isES5: isES5, + propertyIsWritable: function() { + return true; + } + }; +} + +},{}],14:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var PromiseMap = Promise.map; + +Promise.prototype.filter = function (fn, options) { + return PromiseMap(this, fn, options, INTERNAL); +}; + +Promise.filter = function (promises, fn, options) { + return PromiseMap(promises, fn, options, INTERNAL); +}; +}; + +},{}],15:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) { +var util = _dereq_("./util"); +var CancellationError = Promise.CancellationError; +var errorObj = util.errorObj; +var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER); + +function PassThroughHandlerContext(promise, type, handler) { + this.promise = promise; + this.type = type; + this.handler = handler; + this.called = false; + this.cancelPromise = null; +} + +PassThroughHandlerContext.prototype.isFinallyHandler = function() { + return this.type === 0; +}; + +function FinallyHandlerCancelReaction(finallyHandler) { + this.finallyHandler = finallyHandler; +} + +FinallyHandlerCancelReaction.prototype._resultCancelled = function() { + checkCancel(this.finallyHandler); +}; + +function checkCancel(ctx, reason) { + if (ctx.cancelPromise != null) { + if (arguments.length > 1) { + ctx.cancelPromise._reject(reason); + } else { + ctx.cancelPromise._cancel(); + } + ctx.cancelPromise = null; + return true; + } + return false; +} + +function succeed() { + return finallyHandler.call(this, this.promise._target()._settledValue()); +} +function fail(reason) { + if (checkCancel(this, reason)) return; + errorObj.e = reason; + return errorObj; +} +function finallyHandler(reasonOrValue) { + var promise = this.promise; + var handler = this.handler; + + if (!this.called) { + this.called = true; + var ret = this.isFinallyHandler() + ? handler.call(promise._boundValue()) + : handler.call(promise._boundValue(), reasonOrValue); + if (ret === NEXT_FILTER) { + return ret; + } else if (ret !== undefined) { + promise._setReturnedNonUndefined(); + var maybePromise = tryConvertToPromise(ret, promise); + if (maybePromise instanceof Promise) { + if (this.cancelPromise != null) { + if (maybePromise._isCancelled()) { + var reason = + new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + errorObj.e = reason; + return errorObj; + } else if (maybePromise.isPending()) { + maybePromise._attachCancellationCallback( + new FinallyHandlerCancelReaction(this)); + } + } + return maybePromise._then( + succeed, fail, undefined, this, undefined); + } + } + } + + if (promise.isRejected()) { + checkCancel(this); + errorObj.e = reasonOrValue; + return errorObj; + } else { + checkCancel(this); + return reasonOrValue; + } +} + +Promise.prototype._passThrough = function(handler, type, success, fail) { + if (typeof handler !== "function") return this.then(); + return this._then(success, + fail, + undefined, + new PassThroughHandlerContext(this, type, handler), + undefined); +}; + +Promise.prototype.lastly = +Promise.prototype["finally"] = function (handler) { + return this._passThrough(handler, + 0, + finallyHandler, + finallyHandler); +}; + + +Promise.prototype.tap = function (handler) { + return this._passThrough(handler, 1, finallyHandler); +}; + +Promise.prototype.tapCatch = function (handlerOrPredicate) { + var len = arguments.length; + if(len === 1) { + return this._passThrough(handlerOrPredicate, + 1, + undefined, + finallyHandler); + } else { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return Promise.reject(new TypeError( + "tapCatch statement predicate: " + + "expecting an object but got " + util.classString(item) + )); + } + } + catchInstances.length = j; + var handler = arguments[i]; + return this._passThrough(catchFilter(catchInstances, handler, this), + 1, + undefined, + finallyHandler); + } + +}; + +return PassThroughHandlerContext; +}; + +},{"./catch_filter":7,"./util":36}],16:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + apiRejection, + INTERNAL, + tryConvertToPromise, + Proxyable, + debug) { +var errors = _dereq_("./errors"); +var TypeError = errors.TypeError; +var util = _dereq_("./util"); +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +var yieldHandlers = []; + +function promiseFromYieldHandler(value, yieldHandlers, traceParent) { + for (var i = 0; i < yieldHandlers.length; ++i) { + traceParent._pushContext(); + var result = tryCatch(yieldHandlers[i])(value); + traceParent._popContext(); + if (result === errorObj) { + traceParent._pushContext(); + var ret = Promise.reject(errorObj.e); + traceParent._popContext(); + return ret; + } + var maybePromise = tryConvertToPromise(result, traceParent); + if (maybePromise instanceof Promise) return maybePromise; + } + return null; +} + +function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) { + if (debug.cancellation()) { + var internal = new Promise(INTERNAL); + var _finallyPromise = this._finallyPromise = new Promise(INTERNAL); + this._promise = internal.lastly(function() { + return _finallyPromise; + }); + internal._captureStackTrace(); + internal._setOnCancel(this); + } else { + var promise = this._promise = new Promise(INTERNAL); + promise._captureStackTrace(); + } + this._stack = stack; + this._generatorFunction = generatorFunction; + this._receiver = receiver; + this._generator = undefined; + this._yieldHandlers = typeof yieldHandler === "function" + ? [yieldHandler].concat(yieldHandlers) + : yieldHandlers; + this._yieldedPromise = null; + this._cancellationPhase = false; +} +util.inherits(PromiseSpawn, Proxyable); + +PromiseSpawn.prototype._isResolved = function() { + return this._promise === null; +}; + +PromiseSpawn.prototype._cleanup = function() { + this._promise = this._generator = null; + if (debug.cancellation() && this._finallyPromise !== null) { + this._finallyPromise._fulfill(); + this._finallyPromise = null; + } +}; + +PromiseSpawn.prototype._promiseCancelled = function() { + if (this._isResolved()) return; + var implementsReturn = typeof this._generator["return"] !== "undefined"; + + var result; + if (!implementsReturn) { + var reason = new Promise.CancellationError( + "generator .return() sentinel"); + Promise.coroutine.returnSentinel = reason; + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + result = tryCatch(this._generator["throw"]).call(this._generator, + reason); + this._promise._popContext(); + } else { + this._promise._pushContext(); + result = tryCatch(this._generator["return"]).call(this._generator, + undefined); + this._promise._popContext(); + } + this._cancellationPhase = true; + this._yieldedPromise = null; + this._continue(result); +}; + +PromiseSpawn.prototype._promiseFulfilled = function(value) { + this._yieldedPromise = null; + this._promise._pushContext(); + var result = tryCatch(this._generator.next).call(this._generator, value); + this._promise._popContext(); + this._continue(result); +}; + +PromiseSpawn.prototype._promiseRejected = function(reason) { + this._yieldedPromise = null; + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + var result = tryCatch(this._generator["throw"]) + .call(this._generator, reason); + this._promise._popContext(); + this._continue(result); +}; + +PromiseSpawn.prototype._resultCancelled = function() { + if (this._yieldedPromise instanceof Promise) { + var promise = this._yieldedPromise; + this._yieldedPromise = null; + promise.cancel(); + } +}; + +PromiseSpawn.prototype.promise = function () { + return this._promise; +}; + +PromiseSpawn.prototype._run = function () { + this._generator = this._generatorFunction.call(this._receiver); + this._receiver = + this._generatorFunction = undefined; + this._promiseFulfilled(undefined); +}; + +PromiseSpawn.prototype._continue = function (result) { + var promise = this._promise; + if (result === errorObj) { + this._cleanup(); + if (this._cancellationPhase) { + return promise.cancel(); + } else { + return promise._rejectCallback(result.e, false); + } + } + + var value = result.value; + if (result.done === true) { + this._cleanup(); + if (this._cancellationPhase) { + return promise.cancel(); + } else { + return promise._resolveCallback(value); + } + } else { + var maybePromise = tryConvertToPromise(value, this._promise); + if (!(maybePromise instanceof Promise)) { + maybePromise = + promiseFromYieldHandler(maybePromise, + this._yieldHandlers, + this._promise); + if (maybePromise === null) { + this._promiseRejected( + new TypeError( + "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", String(value)) + + "From coroutine:\u000a" + + this._stack.split("\n").slice(1, -7).join("\n") + ) + ); + return; + } + } + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + this._yieldedPromise = maybePromise; + maybePromise._proxy(this, null); + } else if (((bitField & 33554432) !== 0)) { + Promise._async.invoke( + this._promiseFulfilled, this, maybePromise._value() + ); + } else if (((bitField & 16777216) !== 0)) { + Promise._async.invoke( + this._promiseRejected, this, maybePromise._reason() + ); + } else { + this._promiseCancelled(); + } + } +}; + +Promise.coroutine = function (generatorFunction, options) { + if (typeof generatorFunction !== "function") { + throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var yieldHandler = Object(options).yieldHandler; + var PromiseSpawn$ = PromiseSpawn; + var stack = new Error().stack; + return function () { + var generator = generatorFunction.apply(this, arguments); + var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler, + stack); + var ret = spawn.promise(); + spawn._generator = generator; + spawn._promiseFulfilled(undefined); + return ret; + }; +}; + +Promise.coroutine.addYieldHandler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + yieldHandlers.push(fn); +}; + +Promise.spawn = function (generatorFunction) { + debug.deprecated("Promise.spawn()", "Promise.coroutine()"); + if (typeof generatorFunction !== "function") { + return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var spawn = new PromiseSpawn(generatorFunction, this); + var ret = spawn.promise(); + spawn._run(Promise.spawn); + return ret; +}; +}; + +},{"./errors":12,"./util":36}],17:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, + getDomain) { +var util = _dereq_("./util"); +var canEvaluate = util.canEvaluate; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var reject; + +if (false) { +if (canEvaluate) { + var thenCallback = function(i) { + return new Function("value", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = value; \n\ + holder.checkFulfillment(this); \n\ + ".replace(/Index/g, i)); + }; + + var promiseSetter = function(i) { + return new Function("promise", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = promise; \n\ + ".replace(/Index/g, i)); + }; + + var generateHolderClass = function(total) { + var props = new Array(total); + for (var i = 0; i < props.length; ++i) { + props[i] = "this.p" + (i+1); + } + var assignment = props.join(" = ") + " = null;"; + var cancellationCode= "var promise;\n" + props.map(function(prop) { + return " \n\ + promise = " + prop + "; \n\ + if (promise instanceof Promise) { \n\ + promise.cancel(); \n\ + } \n\ + "; + }).join("\n"); + var passedArguments = props.join(", "); + var name = "Holder$" + total; + + + var code = "return function(tryCatch, errorObj, Promise, async) { \n\ + 'use strict'; \n\ + function [TheName](fn) { \n\ + [TheProperties] \n\ + this.fn = fn; \n\ + this.asyncNeeded = true; \n\ + this.now = 0; \n\ + } \n\ + \n\ + [TheName].prototype._callFunction = function(promise) { \n\ + promise._pushContext(); \n\ + var ret = tryCatch(this.fn)([ThePassedArguments]); \n\ + promise._popContext(); \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(ret.e, false); \n\ + } else { \n\ + promise._resolveCallback(ret); \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype.checkFulfillment = function(promise) { \n\ + var now = ++this.now; \n\ + if (now === [TheTotal]) { \n\ + if (this.asyncNeeded) { \n\ + async.invoke(this._callFunction, this, promise); \n\ + } else { \n\ + this._callFunction(promise); \n\ + } \n\ + \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype._resultCancelled = function() { \n\ + [CancellationCode] \n\ + }; \n\ + \n\ + return [TheName]; \n\ + }(tryCatch, errorObj, Promise, async); \n\ + "; + + code = code.replace(/\[TheName\]/g, name) + .replace(/\[TheTotal\]/g, total) + .replace(/\[ThePassedArguments\]/g, passedArguments) + .replace(/\[TheProperties\]/g, assignment) + .replace(/\[CancellationCode\]/g, cancellationCode); + + return new Function("tryCatch", "errorObj", "Promise", "async", code) + (tryCatch, errorObj, Promise, async); + }; + + var holderClasses = []; + var thenCallbacks = []; + var promiseSetters = []; + + for (var i = 0; i < 8; ++i) { + holderClasses.push(generateHolderClass(i + 1)); + thenCallbacks.push(thenCallback(i + 1)); + promiseSetters.push(promiseSetter(i + 1)); + } + + reject = function (reason) { + this._reject(reason); + }; +}} + +Promise.join = function () { + var last = arguments.length - 1; + var fn; + if (last > 0 && typeof arguments[last] === "function") { + fn = arguments[last]; + if (false) { + if (last <= 8 && canEvaluate) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var HolderClass = holderClasses[last - 1]; + var holder = new HolderClass(fn); + var callbacks = thenCallbacks; + + for (var i = 0; i < last; ++i) { + var maybePromise = tryConvertToPromise(arguments[i], ret); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + maybePromise._then(callbacks[i], reject, + undefined, ret, holder); + promiseSetters[i](maybePromise, holder); + holder.asyncNeeded = false; + } else if (((bitField & 33554432) !== 0)) { + callbacks[i].call(ret, + maybePromise._value(), holder); + } else if (((bitField & 16777216) !== 0)) { + ret._reject(maybePromise._reason()); + } else { + ret._cancel(); + } + } else { + callbacks[i].call(ret, maybePromise, holder); + } + } + + if (!ret._isFateSealed()) { + if (holder.asyncNeeded) { + var domain = getDomain(); + if (domain !== null) { + holder.fn = util.domainBind(domain, holder.fn); + } + } + ret._setAsyncGuaranteed(); + ret._setOnCancel(holder); + } + return ret; + } + } + } + var args = [].slice.call(arguments);; + if (fn) args.pop(); + var ret = new PromiseArray(args).promise(); + return fn !== undefined ? ret.spread(fn) : ret; +}; + +}; + +},{"./util":36}],18:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL, + debug) { +var getDomain = Promise._getDomain; +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var async = Promise._async; + +function MappingPromiseArray(promises, fn, limit, _filter) { + this.constructor$(promises); + this._promise._captureStackTrace(); + var domain = getDomain(); + this._callback = domain === null ? fn : util.domainBind(domain, fn); + this._preservedValues = _filter === INTERNAL + ? new Array(this.length()) + : null; + this._limit = limit; + this._inFlight = 0; + this._queue = []; + async.invoke(this._asyncInit, this, undefined); +} +util.inherits(MappingPromiseArray, PromiseArray); + +MappingPromiseArray.prototype._asyncInit = function() { + this._init$(undefined, -2); +}; + +MappingPromiseArray.prototype._init = function () {}; + +MappingPromiseArray.prototype._promiseFulfilled = function (value, index) { + var values = this._values; + var length = this.length(); + var preservedValues = this._preservedValues; + var limit = this._limit; + + if (index < 0) { + index = (index * -1) - 1; + values[index] = value; + if (limit >= 1) { + this._inFlight--; + this._drainQueue(); + if (this._isResolved()) return true; + } + } else { + if (limit >= 1 && this._inFlight >= limit) { + values[index] = value; + this._queue.push(index); + return false; + } + if (preservedValues !== null) preservedValues[index] = value; + + var promise = this._promise; + var callback = this._callback; + var receiver = promise._boundValue(); + promise._pushContext(); + var ret = tryCatch(callback).call(receiver, value, index, length); + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, + promiseCreated, + preservedValues !== null ? "Promise.filter" : "Promise.map", + promise + ); + if (ret === errorObj) { + this._reject(ret.e); + return true; + } + + var maybePromise = tryConvertToPromise(ret, this._promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + if (limit >= 1) this._inFlight++; + values[index] = maybePromise; + maybePromise._proxy(this, (index + 1) * -1); + return false; + } else if (((bitField & 33554432) !== 0)) { + ret = maybePromise._value(); + } else if (((bitField & 16777216) !== 0)) { + this._reject(maybePromise._reason()); + return true; + } else { + this._cancel(); + return true; + } + } + values[index] = ret; + } + var totalResolved = ++this._totalResolved; + if (totalResolved >= length) { + if (preservedValues !== null) { + this._filter(values, preservedValues); + } else { + this._resolve(values); + } + return true; + } + return false; +}; + +MappingPromiseArray.prototype._drainQueue = function () { + var queue = this._queue; + var limit = this._limit; + var values = this._values; + while (queue.length > 0 && this._inFlight < limit) { + if (this._isResolved()) return; + var index = queue.pop(); + this._promiseFulfilled(values[index], index); + } +}; + +MappingPromiseArray.prototype._filter = function (booleans, values) { + var len = values.length; + var ret = new Array(len); + var j = 0; + for (var i = 0; i < len; ++i) { + if (booleans[i]) ret[j++] = values[i]; + } + ret.length = j; + this._resolve(ret); +}; + +MappingPromiseArray.prototype.preservedValues = function () { + return this._preservedValues; +}; + +function map(promises, fn, options, _filter) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + + var limit = 0; + if (options !== undefined) { + if (typeof options === "object" && options !== null) { + if (typeof options.concurrency !== "number") { + return Promise.reject( + new TypeError("'concurrency' must be a number but it is " + + util.classString(options.concurrency))); + } + limit = options.concurrency; + } else { + return Promise.reject(new TypeError( + "options argument must be an object but it is " + + util.classString(options))); + } + } + limit = typeof limit === "number" && + isFinite(limit) && limit >= 1 ? limit : 0; + return new MappingPromiseArray(promises, fn, limit, _filter).promise(); +} + +Promise.prototype.map = function (fn, options) { + return map(this, fn, options, null); +}; + +Promise.map = function (promises, fn, options, _filter) { + return map(promises, fn, options, _filter); +}; + + +}; + +},{"./util":36}],19:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) { +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; + +Promise.method = function (fn) { + if (typeof fn !== "function") { + throw new Promise.TypeError("expecting a function but got " + util.classString(fn)); + } + return function () { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value = tryCatch(fn).apply(this, arguments); + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.method", ret); + ret._resolveFromSyncValue(value); + return ret; + }; +}; + +Promise.attempt = Promise["try"] = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value; + if (arguments.length > 1) { + debug.deprecated("calling Promise.try with more than 1 argument"); + var arg = arguments[1]; + var ctx = arguments[2]; + value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg) + : tryCatch(fn).call(ctx, arg); + } else { + value = tryCatch(fn)(); + } + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.try", ret); + ret._resolveFromSyncValue(value); + return ret; +}; + +Promise.prototype._resolveFromSyncValue = function (value) { + if (value === util.errorObj) { + this._rejectCallback(value.e, false); + } else { + this._resolveCallback(value, true); + } +}; +}; + +},{"./util":36}],20:[function(_dereq_,module,exports){ +"use strict"; +var util = _dereq_("./util"); +var maybeWrapAsError = util.maybeWrapAsError; +var errors = _dereq_("./errors"); +var OperationalError = errors.OperationalError; +var es5 = _dereq_("./es5"); + +function isUntypedError(obj) { + return obj instanceof Error && + es5.getPrototypeOf(obj) === Error.prototype; +} + +var rErrorKey = /^(?:name|message|stack|cause)$/; +function wrapAsOperationalError(obj) { + var ret; + if (isUntypedError(obj)) { + ret = new OperationalError(obj); + ret.name = obj.name; + ret.message = obj.message; + ret.stack = obj.stack; + var keys = es5.keys(obj); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (!rErrorKey.test(key)) { + ret[key] = obj[key]; + } + } + return ret; + } + util.markAsOriginatingFromRejection(obj); + return obj; +} + +function nodebackForPromise(promise, multiArgs) { + return function(err, value) { + if (promise === null) return; + if (err) { + var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); + promise._attachExtraTrace(wrapped); + promise._reject(wrapped); + } else if (!multiArgs) { + promise._fulfill(value); + } else { + var args = [].slice.call(arguments, 1);; + promise._fulfill(args); + } + promise = null; + }; +} + +module.exports = nodebackForPromise; + +},{"./errors":12,"./es5":13,"./util":36}],21:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +var util = _dereq_("./util"); +var async = Promise._async; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +function spreadAdapter(val, nodeback) { + var promise = this; + if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback); + var ret = + tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val)); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} + +function successAdapter(val, nodeback) { + var promise = this; + var receiver = promise._boundValue(); + var ret = val === undefined + ? tryCatch(nodeback).call(receiver, null) + : tryCatch(nodeback).call(receiver, null, val); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} +function errorAdapter(reason, nodeback) { + var promise = this; + if (!reason) { + var newReason = new Error(reason + ""); + newReason.cause = reason; + reason = newReason; + } + var ret = tryCatch(nodeback).call(promise._boundValue(), reason); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} + +Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback, + options) { + if (typeof nodeback == "function") { + var adapter = successAdapter; + if (options !== undefined && Object(options).spread) { + adapter = spreadAdapter; + } + this._then( + adapter, + errorAdapter, + undefined, + this, + nodeback + ); + } + return this; +}; +}; + +},{"./util":36}],22:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function() { +var makeSelfResolutionError = function () { + return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/MqrFmX\u000a"); +}; +var reflectHandler = function() { + return new Promise.PromiseInspection(this._target()); +}; +var apiRejection = function(msg) { + return Promise.reject(new TypeError(msg)); +}; +function Proxyable() {} +var UNDEFINED_BINDING = {}; +var util = _dereq_("./util"); + +var getDomain; +if (util.isNode) { + getDomain = function() { + var ret = process.domain; + if (ret === undefined) ret = null; + return ret; + }; +} else { + getDomain = function() { + return null; + }; +} +util.notEnumerableProp(Promise, "_getDomain", getDomain); + +var es5 = _dereq_("./es5"); +var Async = _dereq_("./async"); +var async = new Async(); +es5.defineProperty(Promise, "_async", {value: async}); +var errors = _dereq_("./errors"); +var TypeError = Promise.TypeError = errors.TypeError; +Promise.RangeError = errors.RangeError; +var CancellationError = Promise.CancellationError = errors.CancellationError; +Promise.TimeoutError = errors.TimeoutError; +Promise.OperationalError = errors.OperationalError; +Promise.RejectionError = errors.OperationalError; +Promise.AggregateError = errors.AggregateError; +var INTERNAL = function(){}; +var APPLY = {}; +var NEXT_FILTER = {}; +var tryConvertToPromise = _dereq_("./thenables")(Promise, INTERNAL); +var PromiseArray = + _dereq_("./promise_array")(Promise, INTERNAL, + tryConvertToPromise, apiRejection, Proxyable); +var Context = _dereq_("./context")(Promise); + /*jshint unused:false*/ +var createContext = Context.create; +var debug = _dereq_("./debuggability")(Promise, Context); +var CapturedTrace = debug.CapturedTrace; +var PassThroughHandlerContext = + _dereq_("./finally")(Promise, tryConvertToPromise, NEXT_FILTER); +var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER); +var nodebackForPromise = _dereq_("./nodeback"); +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +function check(self, executor) { + if (self == null || self.constructor !== Promise) { + throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (typeof executor !== "function") { + throw new TypeError("expecting a function but got " + util.classString(executor)); + } + +} + +function Promise(executor) { + if (executor !== INTERNAL) { + check(this, executor); + } + this._bitField = 0; + this._fulfillmentHandler0 = undefined; + this._rejectionHandler0 = undefined; + this._promise0 = undefined; + this._receiver0 = undefined; + this._resolveFromExecutor(executor); + this._promiseCreated(); + this._fireEvent("promiseCreated", this); +} + +Promise.prototype.toString = function () { + return "[object Promise]"; +}; + +Promise.prototype.caught = Promise.prototype["catch"] = function (fn) { + var len = arguments.length; + if (len > 1) { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return apiRejection("Catch statement predicate: " + + "expecting an object but got " + util.classString(item)); + } + } + catchInstances.length = j; + fn = arguments[i]; + return this.then(undefined, catchFilter(catchInstances, fn, this)); + } + return this.then(undefined, fn); +}; + +Promise.prototype.reflect = function () { + return this._then(reflectHandler, + reflectHandler, undefined, this, undefined); +}; + +Promise.prototype.then = function (didFulfill, didReject) { + if (debug.warnings() && arguments.length > 0 && + typeof didFulfill !== "function" && + typeof didReject !== "function") { + var msg = ".then() only accepts functions but was passed: " + + util.classString(didFulfill); + if (arguments.length > 1) { + msg += ", " + util.classString(didReject); + } + this._warn(msg); + } + return this._then(didFulfill, didReject, undefined, undefined, undefined); +}; + +Promise.prototype.done = function (didFulfill, didReject) { + var promise = + this._then(didFulfill, didReject, undefined, undefined, undefined); + promise._setIsFinal(); +}; + +Promise.prototype.spread = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + return this.all()._then(fn, undefined, undefined, APPLY, undefined); +}; + +Promise.prototype.toJSON = function () { + var ret = { + isFulfilled: false, + isRejected: false, + fulfillmentValue: undefined, + rejectionReason: undefined + }; + if (this.isFulfilled()) { + ret.fulfillmentValue = this.value(); + ret.isFulfilled = true; + } else if (this.isRejected()) { + ret.rejectionReason = this.reason(); + ret.isRejected = true; + } + return ret; +}; + +Promise.prototype.all = function () { + if (arguments.length > 0) { + this._warn(".all() was passed arguments but it does not take any"); + } + return new PromiseArray(this).promise(); +}; + +Promise.prototype.error = function (fn) { + return this.caught(util.originatesFromRejection, fn); +}; + +Promise.getNewLibraryCopy = module.exports; + +Promise.is = function (val) { + return val instanceof Promise; +}; + +Promise.fromNode = Promise.fromCallback = function(fn) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs + : false; + var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs)); + if (result === errorObj) { + ret._rejectCallback(result.e, true); + } + if (!ret._isFateSealed()) ret._setAsyncGuaranteed(); + return ret; +}; + +Promise.all = function (promises) { + return new PromiseArray(promises).promise(); +}; + +Promise.cast = function (obj) { + var ret = tryConvertToPromise(obj); + if (!(ret instanceof Promise)) { + ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._setFulfilled(); + ret._rejectionHandler0 = obj; + } + return ret; +}; + +Promise.resolve = Promise.fulfilled = Promise.cast; + +Promise.reject = Promise.rejected = function (reason) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._rejectCallback(reason, true); + return ret; +}; + +Promise.setScheduler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + return async.setScheduler(fn); +}; + +Promise.prototype._then = function ( + didFulfill, + didReject, + _, receiver, + internalData +) { + var haveInternalData = internalData !== undefined; + var promise = haveInternalData ? internalData : new Promise(INTERNAL); + var target = this._target(); + var bitField = target._bitField; + + if (!haveInternalData) { + promise._propagateFrom(this, 3); + promise._captureStackTrace(); + if (receiver === undefined && + ((this._bitField & 2097152) !== 0)) { + if (!((bitField & 50397184) === 0)) { + receiver = this._boundValue(); + } else { + receiver = target === this ? undefined : this._boundTo; + } + } + this._fireEvent("promiseChained", this, promise); + } + + var domain = getDomain(); + if (!((bitField & 50397184) === 0)) { + var handler, value, settler = target._settlePromiseCtx; + if (((bitField & 33554432) !== 0)) { + value = target._rejectionHandler0; + handler = didFulfill; + } else if (((bitField & 16777216) !== 0)) { + value = target._fulfillmentHandler0; + handler = didReject; + target._unsetRejectionIsUnhandled(); + } else { + settler = target._settlePromiseLateCancellationObserver; + value = new CancellationError("late cancellation observer"); + target._attachExtraTrace(value); + handler = didReject; + } + + async.invoke(settler, target, { + handler: domain === null ? handler + : (typeof handler === "function" && + util.domainBind(domain, handler)), + promise: promise, + receiver: receiver, + value: value + }); + } else { + target._addCallbacks(didFulfill, didReject, promise, receiver, domain); + } + + return promise; +}; + +Promise.prototype._length = function () { + return this._bitField & 65535; +}; + +Promise.prototype._isFateSealed = function () { + return (this._bitField & 117506048) !== 0; +}; + +Promise.prototype._isFollowing = function () { + return (this._bitField & 67108864) === 67108864; +}; + +Promise.prototype._setLength = function (len) { + this._bitField = (this._bitField & -65536) | + (len & 65535); +}; + +Promise.prototype._setFulfilled = function () { + this._bitField = this._bitField | 33554432; + this._fireEvent("promiseFulfilled", this); +}; + +Promise.prototype._setRejected = function () { + this._bitField = this._bitField | 16777216; + this._fireEvent("promiseRejected", this); +}; + +Promise.prototype._setFollowing = function () { + this._bitField = this._bitField | 67108864; + this._fireEvent("promiseResolved", this); +}; + +Promise.prototype._setIsFinal = function () { + this._bitField = this._bitField | 4194304; +}; + +Promise.prototype._isFinal = function () { + return (this._bitField & 4194304) > 0; +}; + +Promise.prototype._unsetCancelled = function() { + this._bitField = this._bitField & (~65536); +}; + +Promise.prototype._setCancelled = function() { + this._bitField = this._bitField | 65536; + this._fireEvent("promiseCancelled", this); +}; + +Promise.prototype._setWillBeCancelled = function() { + this._bitField = this._bitField | 8388608; +}; + +Promise.prototype._setAsyncGuaranteed = function() { + if (async.hasCustomScheduler()) return; + this._bitField = this._bitField | 134217728; +}; + +Promise.prototype._receiverAt = function (index) { + var ret = index === 0 ? this._receiver0 : this[ + index * 4 - 4 + 3]; + if (ret === UNDEFINED_BINDING) { + return undefined; + } else if (ret === undefined && this._isBound()) { + return this._boundValue(); + } + return ret; +}; + +Promise.prototype._promiseAt = function (index) { + return this[ + index * 4 - 4 + 2]; +}; + +Promise.prototype._fulfillmentHandlerAt = function (index) { + return this[ + index * 4 - 4 + 0]; +}; + +Promise.prototype._rejectionHandlerAt = function (index) { + return this[ + index * 4 - 4 + 1]; +}; + +Promise.prototype._boundValue = function() {}; + +Promise.prototype._migrateCallback0 = function (follower) { + var bitField = follower._bitField; + var fulfill = follower._fulfillmentHandler0; + var reject = follower._rejectionHandler0; + var promise = follower._promise0; + var receiver = follower._receiverAt(0); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); +}; + +Promise.prototype._migrateCallbackAt = function (follower, index) { + var fulfill = follower._fulfillmentHandlerAt(index); + var reject = follower._rejectionHandlerAt(index); + var promise = follower._promiseAt(index); + var receiver = follower._receiverAt(index); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); +}; + +Promise.prototype._addCallbacks = function ( + fulfill, + reject, + promise, + receiver, + domain +) { + var index = this._length(); + + if (index >= 65535 - 4) { + index = 0; + this._setLength(0); + } + + if (index === 0) { + this._promise0 = promise; + this._receiver0 = receiver; + if (typeof fulfill === "function") { + this._fulfillmentHandler0 = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this._rejectionHandler0 = + domain === null ? reject : util.domainBind(domain, reject); + } + } else { + var base = index * 4 - 4; + this[base + 2] = promise; + this[base + 3] = receiver; + if (typeof fulfill === "function") { + this[base + 0] = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this[base + 1] = + domain === null ? reject : util.domainBind(domain, reject); + } + } + this._setLength(index + 1); + return index; +}; + +Promise.prototype._proxy = function (proxyable, arg) { + this._addCallbacks(undefined, undefined, arg, proxyable, null); +}; + +Promise.prototype._resolveCallback = function(value, shouldBind) { + if (((this._bitField & 117506048) !== 0)) return; + if (value === this) + return this._rejectCallback(makeSelfResolutionError(), false); + var maybePromise = tryConvertToPromise(value, this); + if (!(maybePromise instanceof Promise)) return this._fulfill(value); + + if (shouldBind) this._propagateFrom(maybePromise, 2); + + var promise = maybePromise._target(); + + if (promise === this) { + this._reject(makeSelfResolutionError()); + return; + } + + var bitField = promise._bitField; + if (((bitField & 50397184) === 0)) { + var len = this._length(); + if (len > 0) promise._migrateCallback0(this); + for (var i = 1; i < len; ++i) { + promise._migrateCallbackAt(this, i); + } + this._setFollowing(); + this._setLength(0); + this._setFollowee(promise); + } else if (((bitField & 33554432) !== 0)) { + this._fulfill(promise._value()); + } else if (((bitField & 16777216) !== 0)) { + this._reject(promise._reason()); + } else { + var reason = new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + this._reject(reason); + } +}; + +Promise.prototype._rejectCallback = +function(reason, synchronous, ignoreNonErrorWarnings) { + var trace = util.ensureErrorObject(reason); + var hasStack = trace === reason; + if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) { + var message = "a promise was rejected with a non-error: " + + util.classString(reason); + this._warn(message, true); + } + this._attachExtraTrace(trace, synchronous ? hasStack : false); + this._reject(reason); +}; + +Promise.prototype._resolveFromExecutor = function (executor) { + if (executor === INTERNAL) return; + var promise = this; + this._captureStackTrace(); + this._pushContext(); + var synchronous = true; + var r = this._execute(executor, function(value) { + promise._resolveCallback(value); + }, function (reason) { + promise._rejectCallback(reason, synchronous); + }); + synchronous = false; + this._popContext(); + + if (r !== undefined) { + promise._rejectCallback(r, true); + } +}; + +Promise.prototype._settlePromiseFromHandler = function ( + handler, receiver, value, promise +) { + var bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + promise._pushContext(); + var x; + if (receiver === APPLY) { + if (!value || typeof value.length !== "number") { + x = errorObj; + x.e = new TypeError("cannot .spread() a non-array: " + + util.classString(value)); + } else { + x = tryCatch(handler).apply(this._boundValue(), value); + } + } else { + x = tryCatch(handler).call(receiver, value); + } + var promiseCreated = promise._popContext(); + bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + + if (x === NEXT_FILTER) { + promise._reject(value); + } else if (x === errorObj) { + promise._rejectCallback(x.e, false); + } else { + debug.checkForgottenReturns(x, promiseCreated, "", promise, this); + promise._resolveCallback(x); + } +}; + +Promise.prototype._target = function() { + var ret = this; + while (ret._isFollowing()) ret = ret._followee(); + return ret; +}; + +Promise.prototype._followee = function() { + return this._rejectionHandler0; +}; + +Promise.prototype._setFollowee = function(promise) { + this._rejectionHandler0 = promise; +}; + +Promise.prototype._settlePromise = function(promise, handler, receiver, value) { + var isPromise = promise instanceof Promise; + var bitField = this._bitField; + var asyncGuaranteed = ((bitField & 134217728) !== 0); + if (((bitField & 65536) !== 0)) { + if (isPromise) promise._invokeInternalOnCancel(); + + if (receiver instanceof PassThroughHandlerContext && + receiver.isFinallyHandler()) { + receiver.cancelPromise = promise; + if (tryCatch(handler).call(receiver, value) === errorObj) { + promise._reject(errorObj.e); + } + } else if (handler === reflectHandler) { + promise._fulfill(reflectHandler.call(receiver)); + } else if (receiver instanceof Proxyable) { + receiver._promiseCancelled(promise); + } else if (isPromise || promise instanceof PromiseArray) { + promise._cancel(); + } else { + receiver.cancel(); + } + } else if (typeof handler === "function") { + if (!isPromise) { + handler.call(receiver, value, promise); + } else { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (receiver instanceof Proxyable) { + if (!receiver._isResolved()) { + if (((bitField & 33554432) !== 0)) { + receiver._promiseFulfilled(value, promise); + } else { + receiver._promiseRejected(value, promise); + } + } + } else if (isPromise) { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + if (((bitField & 33554432) !== 0)) { + promise._fulfill(value); + } else { + promise._reject(value); + } + } +}; + +Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) { + var handler = ctx.handler; + var promise = ctx.promise; + var receiver = ctx.receiver; + var value = ctx.value; + if (typeof handler === "function") { + if (!(promise instanceof Promise)) { + handler.call(receiver, value, promise); + } else { + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (promise instanceof Promise) { + promise._reject(value); + } +}; + +Promise.prototype._settlePromiseCtx = function(ctx) { + this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value); +}; + +Promise.prototype._settlePromise0 = function(handler, value, bitField) { + var promise = this._promise0; + var receiver = this._receiverAt(0); + this._promise0 = undefined; + this._receiver0 = undefined; + this._settlePromise(promise, handler, receiver, value); +}; + +Promise.prototype._clearCallbackDataAtIndex = function(index) { + var base = index * 4 - 4; + this[base + 2] = + this[base + 3] = + this[base + 0] = + this[base + 1] = undefined; +}; + +Promise.prototype._fulfill = function (value) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + if (value === this) { + var err = makeSelfResolutionError(); + this._attachExtraTrace(err); + return this._reject(err); + } + this._setFulfilled(); + this._rejectionHandler0 = value; + + if ((bitField & 65535) > 0) { + if (((bitField & 134217728) !== 0)) { + this._settlePromises(); + } else { + async.settlePromises(this); + } + } +}; + +Promise.prototype._reject = function (reason) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + this._setRejected(); + this._fulfillmentHandler0 = reason; + + if (this._isFinal()) { + return async.fatalError(reason, util.isNode); + } + + if ((bitField & 65535) > 0) { + async.settlePromises(this); + } else { + this._ensurePossibleRejectionHandled(); + } +}; + +Promise.prototype._fulfillPromises = function (len, value) { + for (var i = 1; i < len; i++) { + var handler = this._fulfillmentHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, value); + } +}; + +Promise.prototype._rejectPromises = function (len, reason) { + for (var i = 1; i < len; i++) { + var handler = this._rejectionHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, reason); + } +}; + +Promise.prototype._settlePromises = function () { + var bitField = this._bitField; + var len = (bitField & 65535); + + if (len > 0) { + if (((bitField & 16842752) !== 0)) { + var reason = this._fulfillmentHandler0; + this._settlePromise0(this._rejectionHandler0, reason, bitField); + this._rejectPromises(len, reason); + } else { + var value = this._rejectionHandler0; + this._settlePromise0(this._fulfillmentHandler0, value, bitField); + this._fulfillPromises(len, value); + } + this._setLength(0); + } + this._clearCancellationData(); +}; + +Promise.prototype._settledValue = function() { + var bitField = this._bitField; + if (((bitField & 33554432) !== 0)) { + return this._rejectionHandler0; + } else if (((bitField & 16777216) !== 0)) { + return this._fulfillmentHandler0; + } +}; + +function deferResolve(v) {this.promise._resolveCallback(v);} +function deferReject(v) {this.promise._rejectCallback(v, false);} + +Promise.defer = Promise.pending = function() { + debug.deprecated("Promise.defer", "new Promise"); + var promise = new Promise(INTERNAL); + return { + promise: promise, + resolve: deferResolve, + reject: deferReject + }; +}; + +util.notEnumerableProp(Promise, + "_makeSelfResolutionError", + makeSelfResolutionError); + +_dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection, + debug); +_dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug); +_dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug); +_dereq_("./direct_resolve")(Promise); +_dereq_("./synchronous_inspection")(Promise); +_dereq_("./join")( + Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain); +Promise.Promise = Promise; +Promise.version = "3.5.1"; +_dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); +_dereq_('./call_get.js')(Promise); +_dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug); +_dereq_('./timers.js')(Promise, INTERNAL, debug); +_dereq_('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug); +_dereq_('./nodeify.js')(Promise); +_dereq_('./promisify.js')(Promise, INTERNAL); +_dereq_('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection); +_dereq_('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection); +_dereq_('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); +_dereq_('./settle.js')(Promise, PromiseArray, debug); +_dereq_('./some.js')(Promise, PromiseArray, apiRejection); +_dereq_('./filter.js')(Promise, INTERNAL); +_dereq_('./each.js')(Promise, INTERNAL); +_dereq_('./any.js')(Promise); + + util.toFastProperties(Promise); + util.toFastProperties(Promise.prototype); + function fillTypes(value) { + var p = new Promise(INTERNAL); + p._fulfillmentHandler0 = value; + p._rejectionHandler0 = value; + p._promise0 = value; + p._receiver0 = value; + } + // Complete slack tracking, opt out of field-type tracking and + // stabilize map + fillTypes({a: 1}); + fillTypes({b: 2}); + fillTypes({c: 3}); + fillTypes(1); + fillTypes(function(){}); + fillTypes(undefined); + fillTypes(false); + fillTypes(new Promise(INTERNAL)); + debug.setBounds(Async.firstLineError, util.lastLineError); + return Promise; + +}; + +},{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, + apiRejection, Proxyable) { +var util = _dereq_("./util"); +var isArray = util.isArray; + +function toResolutionValue(val) { + switch(val) { + case -2: return []; + case -3: return {}; + case -6: return new Map(); + } +} + +function PromiseArray(values) { + var promise = this._promise = new Promise(INTERNAL); + if (values instanceof Promise) { + promise._propagateFrom(values, 3); + } + promise._setOnCancel(this); + this._values = values; + this._length = 0; + this._totalResolved = 0; + this._init(undefined, -2); +} +util.inherits(PromiseArray, Proxyable); + +PromiseArray.prototype.length = function () { + return this._length; +}; + +PromiseArray.prototype.promise = function () { + return this._promise; +}; + +PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { + var values = tryConvertToPromise(this._values, this._promise); + if (values instanceof Promise) { + values = values._target(); + var bitField = values._bitField; + ; + this._values = values; + + if (((bitField & 50397184) === 0)) { + this._promise._setAsyncGuaranteed(); + return values._then( + init, + this._reject, + undefined, + this, + resolveValueIfEmpty + ); + } else if (((bitField & 33554432) !== 0)) { + values = values._value(); + } else if (((bitField & 16777216) !== 0)) { + return this._reject(values._reason()); + } else { + return this._cancel(); + } + } + values = util.asArray(values); + if (values === null) { + var err = apiRejection( + "expecting an array or an iterable object but got " + util.classString(values)).reason(); + this._promise._rejectCallback(err, false); + return; + } + + if (values.length === 0) { + if (resolveValueIfEmpty === -5) { + this._resolveEmptyArray(); + } + else { + this._resolve(toResolutionValue(resolveValueIfEmpty)); + } + return; + } + this._iterate(values); +}; + +PromiseArray.prototype._iterate = function(values) { + var len = this.getActualLength(values.length); + this._length = len; + this._values = this.shouldCopyValues() ? new Array(len) : this._values; + var result = this._promise; + var isResolved = false; + var bitField = null; + for (var i = 0; i < len; ++i) { + var maybePromise = tryConvertToPromise(values[i], result); + + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + bitField = maybePromise._bitField; + } else { + bitField = null; + } + + if (isResolved) { + if (bitField !== null) { + maybePromise.suppressUnhandledRejections(); + } + } else if (bitField !== null) { + if (((bitField & 50397184) === 0)) { + maybePromise._proxy(this, i); + this._values[i] = maybePromise; + } else if (((bitField & 33554432) !== 0)) { + isResolved = this._promiseFulfilled(maybePromise._value(), i); + } else if (((bitField & 16777216) !== 0)) { + isResolved = this._promiseRejected(maybePromise._reason(), i); + } else { + isResolved = this._promiseCancelled(i); + } + } else { + isResolved = this._promiseFulfilled(maybePromise, i); + } + } + if (!isResolved) result._setAsyncGuaranteed(); +}; + +PromiseArray.prototype._isResolved = function () { + return this._values === null; +}; + +PromiseArray.prototype._resolve = function (value) { + this._values = null; + this._promise._fulfill(value); +}; + +PromiseArray.prototype._cancel = function() { + if (this._isResolved() || !this._promise._isCancellable()) return; + this._values = null; + this._promise._cancel(); +}; + +PromiseArray.prototype._reject = function (reason) { + this._values = null; + this._promise._rejectCallback(reason, false); +}; + +PromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; +}; + +PromiseArray.prototype._promiseCancelled = function() { + this._cancel(); + return true; +}; + +PromiseArray.prototype._promiseRejected = function (reason) { + this._totalResolved++; + this._reject(reason); + return true; +}; + +PromiseArray.prototype._resultCancelled = function() { + if (this._isResolved()) return; + var values = this._values; + this._cancel(); + if (values instanceof Promise) { + values.cancel(); + } else { + for (var i = 0; i < values.length; ++i) { + if (values[i] instanceof Promise) { + values[i].cancel(); + } + } + } +}; + +PromiseArray.prototype.shouldCopyValues = function () { + return true; +}; + +PromiseArray.prototype.getActualLength = function (len) { + return len; +}; + +return PromiseArray; +}; + +},{"./util":36}],24:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var THIS = {}; +var util = _dereq_("./util"); +var nodebackForPromise = _dereq_("./nodeback"); +var withAppended = util.withAppended; +var maybeWrapAsError = util.maybeWrapAsError; +var canEvaluate = util.canEvaluate; +var TypeError = _dereq_("./errors").TypeError; +var defaultSuffix = "Async"; +var defaultPromisified = {__isPromisified__: true}; +var noCopyProps = [ + "arity", "length", + "name", + "arguments", + "caller", + "callee", + "prototype", + "__isPromisified__" +]; +var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$"); + +var defaultFilter = function(name) { + return util.isIdentifier(name) && + name.charAt(0) !== "_" && + name !== "constructor"; +}; + +function propsFilter(key) { + return !noCopyPropsPattern.test(key); +} + +function isPromisified(fn) { + try { + return fn.__isPromisified__ === true; + } + catch (e) { + return false; + } +} + +function hasPromisified(obj, key, suffix) { + var val = util.getDataPropertyOrDefault(obj, key + suffix, + defaultPromisified); + return val ? isPromisified(val) : false; +} +function checkValid(ret, suffix, suffixRegexp) { + for (var i = 0; i < ret.length; i += 2) { + var key = ret[i]; + if (suffixRegexp.test(key)) { + var keyWithoutAsyncSuffix = key.replace(suffixRegexp, ""); + for (var j = 0; j < ret.length; j += 2) { + if (ret[j] === keyWithoutAsyncSuffix) { + throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a See http://goo.gl/MqrFmX\u000a" + .replace("%s", suffix)); + } + } + } + } +} + +function promisifiableMethods(obj, suffix, suffixRegexp, filter) { + var keys = util.inheritedDataKeys(obj); + var ret = []; + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = obj[key]; + var passesDefaultFilter = filter === defaultFilter + ? true : defaultFilter(key, value, obj); + if (typeof value === "function" && + !isPromisified(value) && + !hasPromisified(obj, key, suffix) && + filter(key, value, obj, passesDefaultFilter)) { + ret.push(key, value); + } + } + checkValid(ret, suffix, suffixRegexp); + return ret; +} + +var escapeIdentRegex = function(str) { + return str.replace(/([$])/, "\\$"); +}; + +var makeNodePromisifiedEval; +if (false) { +var switchCaseArgumentOrder = function(likelyArgumentCount) { + var ret = [likelyArgumentCount]; + var min = Math.max(0, likelyArgumentCount - 1 - 3); + for(var i = likelyArgumentCount - 1; i >= min; --i) { + ret.push(i); + } + for(var i = likelyArgumentCount + 1; i <= 3; ++i) { + ret.push(i); + } + return ret; +}; + +var argumentSequence = function(argumentCount) { + return util.filledRange(argumentCount, "_arg", ""); +}; + +var parameterDeclaration = function(parameterCount) { + return util.filledRange( + Math.max(parameterCount, 3), "_arg", ""); +}; + +var parameterCount = function(fn) { + if (typeof fn.length === "number") { + return Math.max(Math.min(fn.length, 1023 + 1), 0); + } + return 0; +}; + +makeNodePromisifiedEval = +function(callback, receiver, originalName, fn, _, multiArgs) { + var newParameterCount = Math.max(0, parameterCount(fn) - 1); + var argumentOrder = switchCaseArgumentOrder(newParameterCount); + var shouldProxyThis = typeof callback === "string" || receiver === THIS; + + function generateCallForArgumentCount(count) { + var args = argumentSequence(count).join(", "); + var comma = count > 0 ? ", " : ""; + var ret; + if (shouldProxyThis) { + ret = "ret = callback.call(this, {{args}}, nodeback); break;\n"; + } else { + ret = receiver === undefined + ? "ret = callback({{args}}, nodeback); break;\n" + : "ret = callback.call(receiver, {{args}}, nodeback); break;\n"; + } + return ret.replace("{{args}}", args).replace(", ", comma); + } + + function generateArgumentSwitchCase() { + var ret = ""; + for (var i = 0; i < argumentOrder.length; ++i) { + ret += "case " + argumentOrder[i] +":" + + generateCallForArgumentCount(argumentOrder[i]); + } + + ret += " \n\ + default: \n\ + var args = new Array(len + 1); \n\ + var i = 0; \n\ + for (var i = 0; i < len; ++i) { \n\ + args[i] = arguments[i]; \n\ + } \n\ + args[i] = nodeback; \n\ + [CodeForCall] \n\ + break; \n\ + ".replace("[CodeForCall]", (shouldProxyThis + ? "ret = callback.apply(this, args);\n" + : "ret = callback.apply(receiver, args);\n")); + return ret; + } + + var getFunctionCode = typeof callback === "string" + ? ("this != null ? this['"+callback+"'] : fn") + : "fn"; + var body = "'use strict'; \n\ + var ret = function (Parameters) { \n\ + 'use strict'; \n\ + var len = arguments.length; \n\ + var promise = new Promise(INTERNAL); \n\ + promise._captureStackTrace(); \n\ + var nodeback = nodebackForPromise(promise, " + multiArgs + "); \n\ + var ret; \n\ + var callback = tryCatch([GetFunctionCode]); \n\ + switch(len) { \n\ + [CodeForSwitchCase] \n\ + } \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\ + } \n\ + if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); \n\ + return promise; \n\ + }; \n\ + notEnumerableProp(ret, '__isPromisified__', true); \n\ + return ret; \n\ + ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase()) + .replace("[GetFunctionCode]", getFunctionCode); + body = body.replace("Parameters", parameterDeclaration(newParameterCount)); + return new Function("Promise", + "fn", + "receiver", + "withAppended", + "maybeWrapAsError", + "nodebackForPromise", + "tryCatch", + "errorObj", + "notEnumerableProp", + "INTERNAL", + body)( + Promise, + fn, + receiver, + withAppended, + maybeWrapAsError, + nodebackForPromise, + util.tryCatch, + util.errorObj, + util.notEnumerableProp, + INTERNAL); +}; +} + +function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) { + var defaultThis = (function() {return this;})(); + var method = callback; + if (typeof method === "string") { + callback = fn; + } + function promisified() { + var _receiver = receiver; + if (receiver === THIS) _receiver = this; + var promise = new Promise(INTERNAL); + promise._captureStackTrace(); + var cb = typeof method === "string" && this !== defaultThis + ? this[method] : callback; + var fn = nodebackForPromise(promise, multiArgs); + try { + cb.apply(_receiver, withAppended(arguments, fn)); + } catch(e) { + promise._rejectCallback(maybeWrapAsError(e), true, true); + } + if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); + return promise; + } + util.notEnumerableProp(promisified, "__isPromisified__", true); + return promisified; +} + +var makeNodePromisified = canEvaluate + ? makeNodePromisifiedEval + : makeNodePromisifiedClosure; + +function promisifyAll(obj, suffix, filter, promisifier, multiArgs) { + var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$"); + var methods = + promisifiableMethods(obj, suffix, suffixRegexp, filter); + + for (var i = 0, len = methods.length; i < len; i+= 2) { + var key = methods[i]; + var fn = methods[i+1]; + var promisifiedKey = key + suffix; + if (promisifier === makeNodePromisified) { + obj[promisifiedKey] = + makeNodePromisified(key, THIS, key, fn, suffix, multiArgs); + } else { + var promisified = promisifier(fn, function() { + return makeNodePromisified(key, THIS, key, + fn, suffix, multiArgs); + }); + util.notEnumerableProp(promisified, "__isPromisified__", true); + obj[promisifiedKey] = promisified; + } + } + util.toFastProperties(obj); + return obj; +} + +function promisify(callback, receiver, multiArgs) { + return makeNodePromisified(callback, receiver, undefined, + callback, null, multiArgs); +} + +Promise.promisify = function (fn, options) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + if (isPromisified(fn)) { + return fn; + } + options = Object(options); + var receiver = options.context === undefined ? THIS : options.context; + var multiArgs = !!options.multiArgs; + var ret = promisify(fn, receiver, multiArgs); + util.copyDescriptors(fn, ret, propsFilter); + return ret; +}; + +Promise.promisifyAll = function (target, options) { + if (typeof target !== "function" && typeof target !== "object") { + throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + options = Object(options); + var multiArgs = !!options.multiArgs; + var suffix = options.suffix; + if (typeof suffix !== "string") suffix = defaultSuffix; + var filter = options.filter; + if (typeof filter !== "function") filter = defaultFilter; + var promisifier = options.promisifier; + if (typeof promisifier !== "function") promisifier = makeNodePromisified; + + if (!util.isIdentifier(suffix)) { + throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + + var keys = util.inheritedDataKeys(target); + for (var i = 0; i < keys.length; ++i) { + var value = target[keys[i]]; + if (keys[i] !== "constructor" && + util.isClass(value)) { + promisifyAll(value.prototype, suffix, filter, promisifier, + multiArgs); + promisifyAll(value, suffix, filter, promisifier, multiArgs); + } + } + + return promisifyAll(target, suffix, filter, promisifier, multiArgs); +}; +}; + + +},{"./errors":12,"./nodeback":20,"./util":36}],25:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function( + Promise, PromiseArray, tryConvertToPromise, apiRejection) { +var util = _dereq_("./util"); +var isObject = util.isObject; +var es5 = _dereq_("./es5"); +var Es6Map; +if (typeof Map === "function") Es6Map = Map; + +var mapToEntries = (function() { + var index = 0; + var size = 0; + + function extractEntry(value, key) { + this[index] = value; + this[index + size] = key; + index++; + } + + return function mapToEntries(map) { + size = map.size; + index = 0; + var ret = new Array(map.size * 2); + map.forEach(extractEntry, ret); + return ret; + }; +})(); + +var entriesToMap = function(entries) { + var ret = new Es6Map(); + var length = entries.length / 2 | 0; + for (var i = 0; i < length; ++i) { + var key = entries[length + i]; + var value = entries[i]; + ret.set(key, value); + } + return ret; +}; + +function PropertiesPromiseArray(obj) { + var isMap = false; + var entries; + if (Es6Map !== undefined && obj instanceof Es6Map) { + entries = mapToEntries(obj); + isMap = true; + } else { + var keys = es5.keys(obj); + var len = keys.length; + entries = new Array(len * 2); + for (var i = 0; i < len; ++i) { + var key = keys[i]; + entries[i] = obj[key]; + entries[i + len] = key; + } + } + this.constructor$(entries); + this._isMap = isMap; + this._init$(undefined, isMap ? -6 : -3); +} +util.inherits(PropertiesPromiseArray, PromiseArray); + +PropertiesPromiseArray.prototype._init = function () {}; + +PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + var val; + if (this._isMap) { + val = entriesToMap(this._values); + } else { + val = {}; + var keyOffset = this.length(); + for (var i = 0, len = this.length(); i < len; ++i) { + val[this._values[i + keyOffset]] = this._values[i]; + } + } + this._resolve(val); + return true; + } + return false; +}; + +PropertiesPromiseArray.prototype.shouldCopyValues = function () { + return false; +}; + +PropertiesPromiseArray.prototype.getActualLength = function (len) { + return len >> 1; +}; + +function props(promises) { + var ret; + var castValue = tryConvertToPromise(promises); + + if (!isObject(castValue)) { + return apiRejection("cannot await properties of a non-object\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } else if (castValue instanceof Promise) { + ret = castValue._then( + Promise.props, undefined, undefined, undefined, undefined); + } else { + ret = new PropertiesPromiseArray(castValue).promise(); + } + + if (castValue instanceof Promise) { + ret._propagateFrom(castValue, 2); + } + return ret; +} + +Promise.prototype.props = function () { + return props(this); +}; + +Promise.props = function (promises) { + return props(promises); +}; +}; + +},{"./es5":13,"./util":36}],26:[function(_dereq_,module,exports){ +"use strict"; +function arrayMove(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + src[j + srcIndex] = void 0; + } +} + +function Queue(capacity) { + this._capacity = capacity; + this._length = 0; + this._front = 0; +} + +Queue.prototype._willBeOverCapacity = function (size) { + return this._capacity < size; +}; + +Queue.prototype._pushOne = function (arg) { + var length = this.length(); + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = arg; + this._length = length + 1; +}; + +Queue.prototype.push = function (fn, receiver, arg) { + var length = this.length() + 3; + if (this._willBeOverCapacity(length)) { + this._pushOne(fn); + this._pushOne(receiver); + this._pushOne(arg); + return; + } + var j = this._front + length - 3; + this._checkCapacity(length); + var wrapMask = this._capacity - 1; + this[(j + 0) & wrapMask] = fn; + this[(j + 1) & wrapMask] = receiver; + this[(j + 2) & wrapMask] = arg; + this._length = length; +}; + +Queue.prototype.shift = function () { + var front = this._front, + ret = this[front]; + + this[front] = undefined; + this._front = (front + 1) & (this._capacity - 1); + this._length--; + return ret; +}; + +Queue.prototype.length = function () { + return this._length; +}; + +Queue.prototype._checkCapacity = function (size) { + if (this._capacity < size) { + this._resizeTo(this._capacity << 1); + } +}; + +Queue.prototype._resizeTo = function (capacity) { + var oldCapacity = this._capacity; + this._capacity = capacity; + var front = this._front; + var length = this._length; + var moveItemsCount = (front + length) & (oldCapacity - 1); + arrayMove(this, 0, this, oldCapacity, moveItemsCount); +}; + +module.exports = Queue; + +},{}],27:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function( + Promise, INTERNAL, tryConvertToPromise, apiRejection) { +var util = _dereq_("./util"); + +var raceLater = function (promise) { + return promise.then(function(array) { + return race(array, promise); + }); +}; + +function race(promises, parent) { + var maybePromise = tryConvertToPromise(promises); + + if (maybePromise instanceof Promise) { + return raceLater(maybePromise); + } else { + promises = util.asArray(promises); + if (promises === null) + return apiRejection("expecting an array or an iterable object but got " + util.classString(promises)); + } + + var ret = new Promise(INTERNAL); + if (parent !== undefined) { + ret._propagateFrom(parent, 3); + } + var fulfill = ret._fulfill; + var reject = ret._reject; + for (var i = 0, len = promises.length; i < len; ++i) { + var val = promises[i]; + + if (val === undefined && !(i in promises)) { + continue; + } + + Promise.cast(val)._then(fulfill, reject, undefined, ret, null); + } + return ret; +} + +Promise.race = function (promises) { + return race(promises, undefined); +}; + +Promise.prototype.race = function () { + return race(this, undefined); +}; + +}; + +},{"./util":36}],28:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL, + debug) { +var getDomain = Promise._getDomain; +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; + +function ReductionPromiseArray(promises, fn, initialValue, _each) { + this.constructor$(promises); + var domain = getDomain(); + this._fn = domain === null ? fn : util.domainBind(domain, fn); + if (initialValue !== undefined) { + initialValue = Promise.resolve(initialValue); + initialValue._attachCancellationCallback(this); + } + this._initialValue = initialValue; + this._currentCancellable = null; + if(_each === INTERNAL) { + this._eachValues = Array(this._length); + } else if (_each === 0) { + this._eachValues = null; + } else { + this._eachValues = undefined; + } + this._promise._captureStackTrace(); + this._init$(undefined, -5); +} +util.inherits(ReductionPromiseArray, PromiseArray); + +ReductionPromiseArray.prototype._gotAccum = function(accum) { + if (this._eachValues !== undefined && + this._eachValues !== null && + accum !== INTERNAL) { + this._eachValues.push(accum); + } +}; + +ReductionPromiseArray.prototype._eachComplete = function(value) { + if (this._eachValues !== null) { + this._eachValues.push(value); + } + return this._eachValues; +}; + +ReductionPromiseArray.prototype._init = function() {}; + +ReductionPromiseArray.prototype._resolveEmptyArray = function() { + this._resolve(this._eachValues !== undefined ? this._eachValues + : this._initialValue); +}; + +ReductionPromiseArray.prototype.shouldCopyValues = function () { + return false; +}; + +ReductionPromiseArray.prototype._resolve = function(value) { + this._promise._resolveCallback(value); + this._values = null; +}; + +ReductionPromiseArray.prototype._resultCancelled = function(sender) { + if (sender === this._initialValue) return this._cancel(); + if (this._isResolved()) return; + this._resultCancelled$(); + if (this._currentCancellable instanceof Promise) { + this._currentCancellable.cancel(); + } + if (this._initialValue instanceof Promise) { + this._initialValue.cancel(); + } +}; + +ReductionPromiseArray.prototype._iterate = function (values) { + this._values = values; + var value; + var i; + var length = values.length; + if (this._initialValue !== undefined) { + value = this._initialValue; + i = 0; + } else { + value = Promise.resolve(values[0]); + i = 1; + } + + this._currentCancellable = value; + + if (!value.isRejected()) { + for (; i < length; ++i) { + var ctx = { + accum: null, + value: values[i], + index: i, + length: length, + array: this + }; + value = value._then(gotAccum, undefined, undefined, ctx, undefined); + } + } + + if (this._eachValues !== undefined) { + value = value + ._then(this._eachComplete, undefined, undefined, this, undefined); + } + value._then(completed, completed, undefined, value, this); +}; + +Promise.prototype.reduce = function (fn, initialValue) { + return reduce(this, fn, initialValue, null); +}; + +Promise.reduce = function (promises, fn, initialValue, _each) { + return reduce(promises, fn, initialValue, _each); +}; + +function completed(valueOrReason, array) { + if (this.isFulfilled()) { + array._resolve(valueOrReason); + } else { + array._reject(valueOrReason); + } +} + +function reduce(promises, fn, initialValue, _each) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var array = new ReductionPromiseArray(promises, fn, initialValue, _each); + return array.promise(); +} + +function gotAccum(accum) { + this.accum = accum; + this.array._gotAccum(accum); + var value = tryConvertToPromise(this.value, this.array._promise); + if (value instanceof Promise) { + this.array._currentCancellable = value; + return value._then(gotValue, undefined, undefined, this, undefined); + } else { + return gotValue.call(this, value); + } +} + +function gotValue(value) { + var array = this.array; + var promise = array._promise; + var fn = tryCatch(array._fn); + promise._pushContext(); + var ret; + if (array._eachValues !== undefined) { + ret = fn.call(promise._boundValue(), value, this.index, this.length); + } else { + ret = fn.call(promise._boundValue(), + this.accum, value, this.index, this.length); + } + if (ret instanceof Promise) { + array._currentCancellable = ret; + } + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, + promiseCreated, + array._eachValues !== undefined ? "Promise.each" : "Promise.reduce", + promise + ); + return ret; +} +}; + +},{"./util":36}],29:[function(_dereq_,module,exports){ +"use strict"; +var util = _dereq_("./util"); +var schedule; +var noAsyncScheduler = function() { + throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a"); +}; +var NativePromise = util.getNativePromise(); +if (util.isNode && typeof MutationObserver === "undefined") { + var GlobalSetImmediate = global.setImmediate; + var ProcessNextTick = process.nextTick; + schedule = util.isRecentNode + ? function(fn) { GlobalSetImmediate.call(global, fn); } + : function(fn) { ProcessNextTick.call(process, fn); }; +} else if (typeof NativePromise === "function" && + typeof NativePromise.resolve === "function") { + var nativePromise = NativePromise.resolve(); + schedule = function(fn) { + nativePromise.then(fn); + }; +} else if ((typeof MutationObserver !== "undefined") && + !(typeof window !== "undefined" && + window.navigator && + (window.navigator.standalone || window.cordova))) { + schedule = (function() { + var div = document.createElement("div"); + var opts = {attributes: true}; + var toggleScheduled = false; + var div2 = document.createElement("div"); + var o2 = new MutationObserver(function() { + div.classList.toggle("foo"); + toggleScheduled = false; + }); + o2.observe(div2, opts); + + var scheduleToggle = function() { + if (toggleScheduled) return; + toggleScheduled = true; + div2.classList.toggle("foo"); + }; + + return function schedule(fn) { + var o = new MutationObserver(function() { + o.disconnect(); + fn(); + }); + o.observe(div, opts); + scheduleToggle(); + }; + })(); +} else if (typeof setImmediate !== "undefined") { + schedule = function (fn) { + setImmediate(fn); + }; +} else if (typeof setTimeout !== "undefined") { + schedule = function (fn) { + setTimeout(fn, 0); + }; +} else { + schedule = noAsyncScheduler; +} +module.exports = schedule; + +},{"./util":36}],30:[function(_dereq_,module,exports){ +"use strict"; +module.exports = + function(Promise, PromiseArray, debug) { +var PromiseInspection = Promise.PromiseInspection; +var util = _dereq_("./util"); + +function SettledPromiseArray(values) { + this.constructor$(values); +} +util.inherits(SettledPromiseArray, PromiseArray); + +SettledPromiseArray.prototype._promiseResolved = function (index, inspection) { + this._values[index] = inspection; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; +}; + +SettledPromiseArray.prototype._promiseFulfilled = function (value, index) { + var ret = new PromiseInspection(); + ret._bitField = 33554432; + ret._settledValueField = value; + return this._promiseResolved(index, ret); +}; +SettledPromiseArray.prototype._promiseRejected = function (reason, index) { + var ret = new PromiseInspection(); + ret._bitField = 16777216; + ret._settledValueField = reason; + return this._promiseResolved(index, ret); +}; + +Promise.settle = function (promises) { + debug.deprecated(".settle()", ".reflect()"); + return new SettledPromiseArray(promises).promise(); +}; + +Promise.prototype.settle = function () { + return Promise.settle(this); +}; +}; + +},{"./util":36}],31:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, PromiseArray, apiRejection) { +var util = _dereq_("./util"); +var RangeError = _dereq_("./errors").RangeError; +var AggregateError = _dereq_("./errors").AggregateError; +var isArray = util.isArray; +var CANCELLATION = {}; + + +function SomePromiseArray(values) { + this.constructor$(values); + this._howMany = 0; + this._unwrap = false; + this._initialized = false; +} +util.inherits(SomePromiseArray, PromiseArray); + +SomePromiseArray.prototype._init = function () { + if (!this._initialized) { + return; + } + if (this._howMany === 0) { + this._resolve([]); + return; + } + this._init$(undefined, -5); + var isArrayResolved = isArray(this._values); + if (!this._isResolved() && + isArrayResolved && + this._howMany > this._canPossiblyFulfill()) { + this._reject(this._getRangeError(this.length())); + } +}; + +SomePromiseArray.prototype.init = function () { + this._initialized = true; + this._init(); +}; + +SomePromiseArray.prototype.setUnwrap = function () { + this._unwrap = true; +}; + +SomePromiseArray.prototype.howMany = function () { + return this._howMany; +}; + +SomePromiseArray.prototype.setHowMany = function (count) { + this._howMany = count; +}; + +SomePromiseArray.prototype._promiseFulfilled = function (value) { + this._addFulfilled(value); + if (this._fulfilled() === this.howMany()) { + this._values.length = this.howMany(); + if (this.howMany() === 1 && this._unwrap) { + this._resolve(this._values[0]); + } else { + this._resolve(this._values); + } + return true; + } + return false; + +}; +SomePromiseArray.prototype._promiseRejected = function (reason) { + this._addRejected(reason); + return this._checkOutcome(); +}; + +SomePromiseArray.prototype._promiseCancelled = function () { + if (this._values instanceof Promise || this._values == null) { + return this._cancel(); + } + this._addRejected(CANCELLATION); + return this._checkOutcome(); +}; + +SomePromiseArray.prototype._checkOutcome = function() { + if (this.howMany() > this._canPossiblyFulfill()) { + var e = new AggregateError(); + for (var i = this.length(); i < this._values.length; ++i) { + if (this._values[i] !== CANCELLATION) { + e.push(this._values[i]); + } + } + if (e.length > 0) { + this._reject(e); + } else { + this._cancel(); + } + return true; + } + return false; +}; + +SomePromiseArray.prototype._fulfilled = function () { + return this._totalResolved; +}; + +SomePromiseArray.prototype._rejected = function () { + return this._values.length - this.length(); +}; + +SomePromiseArray.prototype._addRejected = function (reason) { + this._values.push(reason); +}; + +SomePromiseArray.prototype._addFulfilled = function (value) { + this._values[this._totalResolved++] = value; +}; + +SomePromiseArray.prototype._canPossiblyFulfill = function () { + return this.length() - this._rejected(); +}; + +SomePromiseArray.prototype._getRangeError = function (count) { + var message = "Input array must contain at least " + + this._howMany + " items but contains only " + count + " items"; + return new RangeError(message); +}; + +SomePromiseArray.prototype._resolveEmptyArray = function () { + this._reject(this._getRangeError(0)); +}; + +function some(promises, howMany) { + if ((howMany | 0) !== howMany || howMany < 0) { + return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var ret = new SomePromiseArray(promises); + var promise = ret.promise(); + ret.setHowMany(howMany); + ret.init(); + return promise; +} + +Promise.some = function (promises, howMany) { + return some(promises, howMany); +}; + +Promise.prototype.some = function (howMany) { + return some(this, howMany); +}; + +Promise._SomePromiseArray = SomePromiseArray; +}; + +},{"./errors":12,"./util":36}],32:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +function PromiseInspection(promise) { + if (promise !== undefined) { + promise = promise._target(); + this._bitField = promise._bitField; + this._settledValueField = promise._isFateSealed() + ? promise._settledValue() : undefined; + } + else { + this._bitField = 0; + this._settledValueField = undefined; + } +} + +PromiseInspection.prototype._settledValue = function() { + return this._settledValueField; +}; + +var value = PromiseInspection.prototype.value = function () { + if (!this.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); +}; + +var reason = PromiseInspection.prototype.error = +PromiseInspection.prototype.reason = function () { + if (!this.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); +}; + +var isFulfilled = PromiseInspection.prototype.isFulfilled = function() { + return (this._bitField & 33554432) !== 0; +}; + +var isRejected = PromiseInspection.prototype.isRejected = function () { + return (this._bitField & 16777216) !== 0; +}; + +var isPending = PromiseInspection.prototype.isPending = function () { + return (this._bitField & 50397184) === 0; +}; + +var isResolved = PromiseInspection.prototype.isResolved = function () { + return (this._bitField & 50331648) !== 0; +}; + +PromiseInspection.prototype.isCancelled = function() { + return (this._bitField & 8454144) !== 0; +}; + +Promise.prototype.__isCancelled = function() { + return (this._bitField & 65536) === 65536; +}; + +Promise.prototype._isCancelled = function() { + return this._target().__isCancelled(); +}; + +Promise.prototype.isCancelled = function() { + return (this._target()._bitField & 8454144) !== 0; +}; + +Promise.prototype.isPending = function() { + return isPending.call(this._target()); +}; + +Promise.prototype.isRejected = function() { + return isRejected.call(this._target()); +}; + +Promise.prototype.isFulfilled = function() { + return isFulfilled.call(this._target()); +}; + +Promise.prototype.isResolved = function() { + return isResolved.call(this._target()); +}; + +Promise.prototype.value = function() { + return value.call(this._target()); +}; + +Promise.prototype.reason = function() { + var target = this._target(); + target._unsetRejectionIsUnhandled(); + return reason.call(target); +}; + +Promise.prototype._value = function() { + return this._settledValue(); +}; + +Promise.prototype._reason = function() { + this._unsetRejectionIsUnhandled(); + return this._settledValue(); +}; + +Promise.PromiseInspection = PromiseInspection; +}; + +},{}],33:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var util = _dereq_("./util"); +var errorObj = util.errorObj; +var isObject = util.isObject; + +function tryConvertToPromise(obj, context) { + if (isObject(obj)) { + if (obj instanceof Promise) return obj; + var then = getThen(obj); + if (then === errorObj) { + if (context) context._pushContext(); + var ret = Promise.reject(then.e); + if (context) context._popContext(); + return ret; + } else if (typeof then === "function") { + if (isAnyBluebirdPromise(obj)) { + var ret = new Promise(INTERNAL); + obj._then( + ret._fulfill, + ret._reject, + undefined, + ret, + null + ); + return ret; + } + return doThenable(obj, then, context); + } + } + return obj; +} + +function doGetThen(obj) { + return obj.then; +} + +function getThen(obj) { + try { + return doGetThen(obj); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} + +var hasProp = {}.hasOwnProperty; +function isAnyBluebirdPromise(obj) { + try { + return hasProp.call(obj, "_promise0"); + } catch (e) { + return false; + } +} + +function doThenable(x, then, context) { + var promise = new Promise(INTERNAL); + var ret = promise; + if (context) context._pushContext(); + promise._captureStackTrace(); + if (context) context._popContext(); + var synchronous = true; + var result = util.tryCatch(then).call(x, resolve, reject); + synchronous = false; + + if (promise && result === errorObj) { + promise._rejectCallback(result.e, true, true); + promise = null; + } + + function resolve(value) { + if (!promise) return; + promise._resolveCallback(value); + promise = null; + } + + function reject(reason) { + if (!promise) return; + promise._rejectCallback(reason, synchronous, true); + promise = null; + } + return ret; +} + +return tryConvertToPromise; +}; + +},{"./util":36}],34:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, debug) { +var util = _dereq_("./util"); +var TimeoutError = Promise.TimeoutError; + +function HandleWrapper(handle) { + this.handle = handle; +} + +HandleWrapper.prototype._resultCancelled = function() { + clearTimeout(this.handle); +}; + +var afterValue = function(value) { return delay(+this).thenReturn(value); }; +var delay = Promise.delay = function (ms, value) { + var ret; + var handle; + if (value !== undefined) { + ret = Promise.resolve(value) + ._then(afterValue, null, null, ms, undefined); + if (debug.cancellation() && value instanceof Promise) { + ret._setOnCancel(value); + } + } else { + ret = new Promise(INTERNAL); + handle = setTimeout(function() { ret._fulfill(); }, +ms); + if (debug.cancellation()) { + ret._setOnCancel(new HandleWrapper(handle)); + } + ret._captureStackTrace(); + } + ret._setAsyncGuaranteed(); + return ret; +}; + +Promise.prototype.delay = function (ms) { + return delay(ms, this); +}; + +var afterTimeout = function (promise, message, parent) { + var err; + if (typeof message !== "string") { + if (message instanceof Error) { + err = message; + } else { + err = new TimeoutError("operation timed out"); + } + } else { + err = new TimeoutError(message); + } + util.markAsOriginatingFromRejection(err); + promise._attachExtraTrace(err); + promise._reject(err); + + if (parent != null) { + parent.cancel(); + } +}; + +function successClear(value) { + clearTimeout(this.handle); + return value; +} + +function failureClear(reason) { + clearTimeout(this.handle); + throw reason; +} + +Promise.prototype.timeout = function (ms, message) { + ms = +ms; + var ret, parent; + + var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() { + if (ret.isPending()) { + afterTimeout(ret, message, parent); + } + }, ms)); + + if (debug.cancellation()) { + parent = this.then(); + ret = parent._then(successClear, failureClear, + undefined, handleWrapper, undefined); + ret._setOnCancel(handleWrapper); + } else { + ret = this._then(successClear, failureClear, + undefined, handleWrapper, undefined); + } + + return ret; +}; + +}; + +},{"./util":36}],35:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function (Promise, apiRejection, tryConvertToPromise, + createContext, INTERNAL, debug) { + var util = _dereq_("./util"); + var TypeError = _dereq_("./errors").TypeError; + var inherits = _dereq_("./util").inherits; + var errorObj = util.errorObj; + var tryCatch = util.tryCatch; + var NULL = {}; + + function thrower(e) { + setTimeout(function(){throw e;}, 0); + } + + function castPreservingDisposable(thenable) { + var maybePromise = tryConvertToPromise(thenable); + if (maybePromise !== thenable && + typeof thenable._isDisposable === "function" && + typeof thenable._getDisposer === "function" && + thenable._isDisposable()) { + maybePromise._setDisposable(thenable._getDisposer()); + } + return maybePromise; + } + function dispose(resources, inspection) { + var i = 0; + var len = resources.length; + var ret = new Promise(INTERNAL); + function iterator() { + if (i >= len) return ret._fulfill(); + var maybePromise = castPreservingDisposable(resources[i++]); + if (maybePromise instanceof Promise && + maybePromise._isDisposable()) { + try { + maybePromise = tryConvertToPromise( + maybePromise._getDisposer().tryDispose(inspection), + resources.promise); + } catch (e) { + return thrower(e); + } + if (maybePromise instanceof Promise) { + return maybePromise._then(iterator, thrower, + null, null, null); + } + } + iterator(); + } + iterator(); + return ret; + } + + function Disposer(data, promise, context) { + this._data = data; + this._promise = promise; + this._context = context; + } + + Disposer.prototype.data = function () { + return this._data; + }; + + Disposer.prototype.promise = function () { + return this._promise; + }; + + Disposer.prototype.resource = function () { + if (this.promise().isFulfilled()) { + return this.promise().value(); + } + return NULL; + }; + + Disposer.prototype.tryDispose = function(inspection) { + var resource = this.resource(); + var context = this._context; + if (context !== undefined) context._pushContext(); + var ret = resource !== NULL + ? this.doDispose(resource, inspection) : null; + if (context !== undefined) context._popContext(); + this._promise._unsetDisposable(); + this._data = null; + return ret; + }; + + Disposer.isDisposer = function (d) { + return (d != null && + typeof d.resource === "function" && + typeof d.tryDispose === "function"); + }; + + function FunctionDisposer(fn, promise, context) { + this.constructor$(fn, promise, context); + } + inherits(FunctionDisposer, Disposer); + + FunctionDisposer.prototype.doDispose = function (resource, inspection) { + var fn = this.data(); + return fn.call(resource, resource, inspection); + }; + + function maybeUnwrapDisposer(value) { + if (Disposer.isDisposer(value)) { + this.resources[this.index]._setDisposable(value); + return value.promise(); + } + return value; + } + + function ResourceList(length) { + this.length = length; + this.promise = null; + this[length-1] = null; + } + + ResourceList.prototype._resultCancelled = function() { + var len = this.length; + for (var i = 0; i < len; ++i) { + var item = this[i]; + if (item instanceof Promise) { + item.cancel(); + } + } + }; + + Promise.using = function () { + var len = arguments.length; + if (len < 2) return apiRejection( + "you must pass at least 2 arguments to Promise.using"); + var fn = arguments[len - 1]; + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var input; + var spreadArgs = true; + if (len === 2 && Array.isArray(arguments[0])) { + input = arguments[0]; + len = input.length; + spreadArgs = false; + } else { + input = arguments; + len--; + } + var resources = new ResourceList(len); + for (var i = 0; i < len; ++i) { + var resource = input[i]; + if (Disposer.isDisposer(resource)) { + var disposer = resource; + resource = resource.promise(); + resource._setDisposable(disposer); + } else { + var maybePromise = tryConvertToPromise(resource); + if (maybePromise instanceof Promise) { + resource = + maybePromise._then(maybeUnwrapDisposer, null, null, { + resources: resources, + index: i + }, undefined); + } + } + resources[i] = resource; + } + + var reflectedResources = new Array(resources.length); + for (var i = 0; i < reflectedResources.length; ++i) { + reflectedResources[i] = Promise.resolve(resources[i]).reflect(); + } + + var resultPromise = Promise.all(reflectedResources) + .then(function(inspections) { + for (var i = 0; i < inspections.length; ++i) { + var inspection = inspections[i]; + if (inspection.isRejected()) { + errorObj.e = inspection.error(); + return errorObj; + } else if (!inspection.isFulfilled()) { + resultPromise.cancel(); + return; + } + inspections[i] = inspection.value(); + } + promise._pushContext(); + + fn = tryCatch(fn); + var ret = spreadArgs + ? fn.apply(undefined, inspections) : fn(inspections); + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, promiseCreated, "Promise.using", promise); + return ret; + }); + + var promise = resultPromise.lastly(function() { + var inspection = new Promise.PromiseInspection(resultPromise); + return dispose(resources, inspection); + }); + resources.promise = promise; + promise._setOnCancel(resources); + return promise; + }; + + Promise.prototype._setDisposable = function (disposer) { + this._bitField = this._bitField | 131072; + this._disposer = disposer; + }; + + Promise.prototype._isDisposable = function () { + return (this._bitField & 131072) > 0; + }; + + Promise.prototype._getDisposer = function () { + return this._disposer; + }; + + Promise.prototype._unsetDisposable = function () { + this._bitField = this._bitField & (~131072); + this._disposer = undefined; + }; + + Promise.prototype.disposer = function (fn) { + if (typeof fn === "function") { + return new FunctionDisposer(fn, this, createContext()); + } + throw new TypeError(); + }; + +}; + +},{"./errors":12,"./util":36}],36:[function(_dereq_,module,exports){ +"use strict"; +var es5 = _dereq_("./es5"); +var canEvaluate = typeof navigator == "undefined"; + +var errorObj = {e: {}}; +var tryCatchTarget; +var globalObject = typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + this !== undefined ? this : null; + +function tryCatcher() { + try { + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} +function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; +} + +var inherits = function(Child, Parent) { + var hasProp = {}.hasOwnProperty; + + function T() { + this.constructor = Child; + this.constructor$ = Parent; + for (var propertyName in Parent.prototype) { + if (hasProp.call(Parent.prototype, propertyName) && + propertyName.charAt(propertyName.length-1) !== "$" + ) { + this[propertyName + "$"] = Parent.prototype[propertyName]; + } + } + } + T.prototype = Parent.prototype; + Child.prototype = new T(); + return Child.prototype; +}; + + +function isPrimitive(val) { + return val == null || val === true || val === false || + typeof val === "string" || typeof val === "number"; + +} + +function isObject(value) { + return typeof value === "function" || + typeof value === "object" && value !== null; +} + +function maybeWrapAsError(maybeError) { + if (!isPrimitive(maybeError)) return maybeError; + + return new Error(safeToString(maybeError)); +} + +function withAppended(target, appendee) { + var len = target.length; + var ret = new Array(len + 1); + var i; + for (i = 0; i < len; ++i) { + ret[i] = target[i]; + } + ret[i] = appendee; + return ret; +} + +function getDataPropertyOrDefault(obj, key, defaultValue) { + if (es5.isES5) { + var desc = Object.getOwnPropertyDescriptor(obj, key); + + if (desc != null) { + return desc.get == null && desc.set == null + ? desc.value + : defaultValue; + } + } else { + return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; + } +} + +function notEnumerableProp(obj, name, value) { + if (isPrimitive(obj)) return obj; + var descriptor = { + value: value, + configurable: true, + enumerable: false, + writable: true + }; + es5.defineProperty(obj, name, descriptor); + return obj; +} + +function thrower(r) { + throw r; +} + +var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; + + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } + } + return false; + }; + + if (es5.isES5) { + var getKeys = Object.getOwnPropertyNames; + return function(obj) { + var ret = []; + var visitedKeys = Object.create(null); + while (obj != null && !isExcludedProto(obj)) { + var keys; + try { + keys = getKeys(obj); + } catch (e) { + return ret; + } + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (visitedKeys[key]) continue; + visitedKeys[key] = true; + var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null && desc.get == null && desc.set == null) { + ret.push(key); + } + } + obj = es5.getPrototypeOf(obj); + } + return ret; + }; + } else { + var hasProp = {}.hasOwnProperty; + return function(obj) { + if (isExcludedProto(obj)) return []; + var ret = []; + + /*jshint forin:false */ + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } + } + return ret; + }; + } + +})(); + +var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; +function isClass(fn) { + try { + if (typeof fn === "function") { + var keys = es5.names(fn.prototype); + + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; + + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } + } + return false; + } catch (e) { + return false; + } +} + +function toFastProperties(obj) { + /*jshint -W027,-W055,-W031*/ + function FakeConstructor() {} + FakeConstructor.prototype = obj; + var l = 8; + while (l--) new FakeConstructor(); + return obj; + eval(obj); +} + +var rident = /^[a-z$_][a-z$_0-9]*$/i; +function isIdentifier(str) { + return rident.test(str); +} + +function filledRange(count, prefix, suffix) { + var ret = new Array(count); + for(var i = 0; i < count; ++i) { + ret[i] = prefix + i + suffix; + } + return ret; +} + +function safeToString(obj) { + try { + return obj + ""; + } catch (e) { + return "[no string representation]"; + } +} + +function isError(obj) { + return obj instanceof Error || + (obj !== null && + typeof obj === "object" && + typeof obj.message === "string" && + typeof obj.name === "string"); +} + +function markAsOriginatingFromRejection(e) { + try { + notEnumerableProp(e, "isOperational", true); + } + catch(ignore) {} +} + +function originatesFromRejection(e) { + if (e == null) return false; + return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || + e["isOperational"] === true); +} + +function canAttachTrace(obj) { + return isError(obj) && es5.propertyIsWritable(obj, "stack"); +} + +var ensureErrorObject = (function() { + if (!("stack" in new Error())) { + return function(value) { + if (canAttachTrace(value)) return value; + try {throw new Error(safeToString(value));} + catch(err) {return err;} + }; + } else { + return function(value) { + if (canAttachTrace(value)) return value; + return new Error(safeToString(value)); + }; + } +})(); + +function classString(obj) { + return {}.toString.call(obj); +} + +function copyDescriptors(from, to, filter) { + var keys = es5.names(from); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (filter(key)) { + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} + } + } +} + +var asArray = function(v) { + if (es5.isArray(v)) { + return v; + } + return null; +}; + +if (typeof Symbol !== "undefined" && Symbol.iterator) { + var ArrayFrom = typeof Array.from === "function" ? function(v) { + return Array.from(v); + } : function(v) { + var ret = []; + var it = v[Symbol.iterator](); + var itResult; + while (!((itResult = it.next()).done)) { + ret.push(itResult.value); + } + return ret; + }; + + asArray = function(v) { + if (es5.isArray(v)) { + return v; + } else if (v != null && typeof v[Symbol.iterator] === "function") { + return ArrayFrom(v); + } + return null; + }; +} + +var isNode = typeof process !== "undefined" && + classString(process).toLowerCase() === "[object process]"; + +var hasEnvVariables = typeof process !== "undefined" && + typeof process.env !== "undefined"; + +function env(key) { + return hasEnvVariables ? process.env[key] : undefined; +} + +function getNativePromise() { + if (typeof Promise === "function") { + try { + var promise = new Promise(function(){}); + if ({}.toString.call(promise) === "[object Promise]") { + return Promise; + } + } catch (e) {} + } +} + +function domainBind(self, cb) { + return self.bind(cb); +} + +var ret = { + isClass: isClass, + isIdentifier: isIdentifier, + inheritedDataKeys: inheritedDataKeys, + getDataPropertyOrDefault: getDataPropertyOrDefault, + thrower: thrower, + isArray: es5.isArray, + asArray: asArray, + notEnumerableProp: notEnumerableProp, + isPrimitive: isPrimitive, + isObject: isObject, + isError: isError, + canEvaluate: canEvaluate, + errorObj: errorObj, + tryCatch: tryCatch, + inherits: inherits, + withAppended: withAppended, + maybeWrapAsError: maybeWrapAsError, + toFastProperties: toFastProperties, + filledRange: filledRange, + toString: safeToString, + canAttachTrace: canAttachTrace, + ensureErrorObject: ensureErrorObject, + originatesFromRejection: originatesFromRejection, + markAsOriginatingFromRejection: markAsOriginatingFromRejection, + classString: classString, + copyDescriptors: copyDescriptors, + hasDevTools: typeof chrome !== "undefined" && chrome && + typeof chrome.loadTimes === "function", + isNode: isNode, + hasEnvVariables: hasEnvVariables, + env: env, + global: globalObject, + getNativePromise: getNativePromise, + domainBind: domainBind +}; +ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); +})(); + +if (ret.isNode) ret.toFastProperties(process); + +try {throw new Error(); } catch (e) {ret.lastLineError = e;} +module.exports = ret; + +},{"./es5":13}]},{},[4])(4) +}); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(65), __webpack_require__(38), __webpack_require__(389).setImmediate)) + +/***/ }), +/* 389 */ +/***/ (function(module, exports, __webpack_require__) { + +var apply = Function.prototype.apply; + +// DOM APIs, for completeness + +exports.setTimeout = function() { + return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); +}; +exports.setInterval = function() { + return new Timeout(apply.call(setInterval, window, arguments), clearInterval); +}; +exports.clearTimeout = +exports.clearInterval = function(timeout) { + if (timeout) { + timeout.close(); + } +}; + +function Timeout(id, clearFn) { + this._id = id; + this._clearFn = clearFn; +} +Timeout.prototype.unref = Timeout.prototype.ref = function() {}; +Timeout.prototype.close = function() { + this._clearFn.call(window, this._id); +}; + +// Does not start the time, just sets up the members needed. +exports.enroll = function(item, msecs) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = msecs; +}; + +exports.unenroll = function(item) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = -1; +}; + +exports._unrefActive = exports.active = function(item) { + clearTimeout(item._idleTimeoutId); + + var msecs = item._idleTimeout; + if (msecs >= 0) { + item._idleTimeoutId = setTimeout(function onTimeout() { + if (item._onTimeout) + item._onTimeout(); + }, msecs); + } +}; + +// setimmediate attaches itself to the global object +__webpack_require__(390); +exports.setImmediate = setImmediate; +exports.clearImmediate = clearImmediate; + + +/***/ }), +/* 390 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) { + "use strict"; + + if (global.setImmediate) { + return; + } + + var nextHandle = 1; // Spec says greater than zero + var tasksByHandle = {}; + var currentlyRunningATask = false; + var doc = global.document; + var registerImmediate; + + function setImmediate(callback) { + // Callback can either be a function or a string + if (typeof callback !== "function") { + callback = new Function("" + callback); + } + // Copy function arguments + var args = new Array(arguments.length - 1); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i + 1]; + } + // Store and register the task + var task = { callback: callback, args: args }; + tasksByHandle[nextHandle] = task; + registerImmediate(nextHandle); + return nextHandle++; + } + + function clearImmediate(handle) { + delete tasksByHandle[handle]; + } + + function run(task) { + var callback = task.callback; + var args = task.args; + switch (args.length) { + case 0: + callback(); + break; + case 1: + callback(args[0]); + break; + case 2: + callback(args[0], args[1]); + break; + case 3: + callback(args[0], args[1], args[2]); + break; + default: + callback.apply(undefined, args); + break; + } + } + + function runIfPresent(handle) { + // From the spec: "Wait until any invocations of this algorithm started before this one have completed." + // So if we're currently running a task, we'll need to delay this invocation. + if (currentlyRunningATask) { + // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a + // "too much recursion" error. + setTimeout(runIfPresent, 0, handle); + } else { + var task = tasksByHandle[handle]; + if (task) { + currentlyRunningATask = true; + try { + run(task); + } finally { + clearImmediate(handle); + currentlyRunningATask = false; + } + } + } + } + + function installNextTickImplementation() { + registerImmediate = function(handle) { + process.nextTick(function () { runIfPresent(handle); }); + }; + } + + function canUsePostMessage() { + // The test against `importScripts` prevents this implementation from being installed inside a web worker, + // where `global.postMessage` means something completely different and can't be used for this purpose. + if (global.postMessage && !global.importScripts) { + var postMessageIsAsynchronous = true; + var oldOnMessage = global.onmessage; + global.onmessage = function() { + postMessageIsAsynchronous = false; + }; + global.postMessage("", "*"); + global.onmessage = oldOnMessage; + return postMessageIsAsynchronous; + } + } + + function installPostMessageImplementation() { + // Installs an event handler on `global` for the `message` event: see + // * https://developer.mozilla.org/en/DOM/window.postMessage + // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages + + var messagePrefix = "setImmediate$" + Math.random() + "$"; + var onGlobalMessage = function(event) { + if (event.source === global && + typeof event.data === "string" && + event.data.indexOf(messagePrefix) === 0) { + runIfPresent(+event.data.slice(messagePrefix.length)); + } + }; + + if (global.addEventListener) { + global.addEventListener("message", onGlobalMessage, false); + } else { + global.attachEvent("onmessage", onGlobalMessage); + } + + registerImmediate = function(handle) { + global.postMessage(messagePrefix + handle, "*"); + }; + } + + function installMessageChannelImplementation() { + var channel = new MessageChannel(); + channel.port1.onmessage = function(event) { + var handle = event.data; + runIfPresent(handle); + }; + + registerImmediate = function(handle) { + channel.port2.postMessage(handle); + }; + } + + function installReadyStateChangeImplementation() { + var html = doc.documentElement; + registerImmediate = function(handle) { + // Create a + + + diff --git a/myproj/package-lock.json b/myproj/package-lock.json new file mode 100644 index 0000000000..da5667e1ab --- /dev/null +++ b/myproj/package-lock.json @@ -0,0 +1,10012 @@ +{ + "name": "myproj", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/polyfill": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.0.0-beta.32.tgz", + "integrity": "sha512-VhAfJkk1c4wgpfjG/OBxUlq8QEUqsKWhttJI4nO0OHX+gyC2+7AbePbBWxmCKIoZSPAujcySx07/SxXihK0yEA==", + "requires": { + "core-js": "2.5.1", + "regenerator-runtime": "0.11.0" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/inquire": "1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@std/esm": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@std/esm/-/esm-0.16.0.tgz", + "integrity": "sha512-JokzOdnTmxUWJ81VWp0OuSR+VZGuvM9lmnefiPoeTwrOH/wworkRvwkXMpSuso0zYQ0LcbGUKLEdkoKwkYyohg==", + "dev": true + }, + "@types/events": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz", + "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw==" + }, + "@types/long": { + "version": "3.0.32", + "resolved": "https://registry.npmjs.org/@types/long/-/long-3.0.32.tgz", + "integrity": "sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA==" + }, + "@types/node": { + "version": "8.0.54", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.54.tgz", + "integrity": "sha512-qetMdTv3Ytz9u9ESLdcYs45LPI0mczYZIbC184n7kY0jczOqPNQsabBfVCh+na3B2shAfvC459JqHV771A8Rxg==", + "requires": { + "@types/events": "1.1.0" + } + }, + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "dev": true, + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==" + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.0.tgz", + "integrity": "sha1-6yhAdG6dxIvV4GOjbj/UAMXqtak=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "optional": true + }, + "ansi-escapes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", + "dev": true + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-flatten": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", + "dev": true + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1.js": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", + "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "autoprefixer": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.1.6.tgz", + "integrity": "sha512-C9yv/UF3X+eJTi/zvfxuyfxmLibYrntpF3qoJYrMeQwgUJOZrZvpJiMG2FMQ3qnhWtF/be4pYONBBw95ZGe3vA==", + "dev": true, + "requires": { + "browserslist": "2.9.1", + "caniuse-lite": "1.0.30000777", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "6.0.14", + "postcss-value-parser": "3.3.0" + } + }, + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "requires": { + "follow-redirects": "1.2.6", + "is-buffer": "1.1.6" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-eslint": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.2.3.tgz", + "integrity": "sha1-sv4tgBJkcPXBlELcdXJTqJdxCCc=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0" + } + }, + "babel-generator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "dev": true, + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-jest": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-21.2.0.tgz", + "integrity": "sha512-O0W2qLoWu1QOoOGgxiR2JID4O6WSpxPiQanrkyi9SSlM0PJ60Ptzlck47lhtnr9YZO3zYOsxHwnyeWJ6AffoBQ==", + "dev": true, + "requires": { + "babel-plugin-istanbul": "4.1.5", + "babel-preset-jest": "21.2.0" + } + }, + "babel-loader": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.2.tgz", + "integrity": "sha512-jRwlFbINAeyDStqK6Dd5YuY0k5YuzQUvlz2ZamuXrXmxav3pNqe9vfJ402+2G+OmlJSXxCOpB6Uz0INM7RQe2A==", + "dev": true, + "requires": { + "find-cache-dir": "1.0.0", + "loader-utils": "1.1.0", + "mkdirp": "0.5.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-1.2.0.tgz", + "integrity": "sha512-yeDwKaLgGdTpXL7RgGt5r6T4LmnTza/hUn5Ul8uZSGGMtEjYo13Nxai7SQaGCTEzUtg9Zq9qJn0EjEr7SeSlTQ==", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0" + } + }, + "babel-plugin-istanbul": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.5.tgz", + "integrity": "sha1-Z2DN2Xf0EdPhdbsGTyvDJ9mbK24=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "istanbul-lib-instrument": "1.9.1", + "test-exclude": "4.1.1" + } + }, + "babel-plugin-jest-hoist": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-21.2.0.tgz", + "integrity": "sha512-yi5QuiVyyvhBUDLP4ButAnhYzkdrUwWDtvUJv71hjH3fclhnZg4HkDeqaitcR2dZZx/E67kGkRcPVjtVu+SJfQ==", + "dev": true + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", + "dev": true + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", + "dev": true + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", + "dev": true + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "dev": true, + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz", + "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-preset-env": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "2.9.1", + "invariant": "2.2.2", + "semver": "5.4.1" + } + }, + "babel-preset-jest": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-21.2.0.tgz", + "integrity": "sha512-hm9cBnr2h3J7yXoTtAVV0zg+3vg0Q/gT2GYuzlreTU0EPkJRtlNgKJJ3tBKEn0+VjAi3JykV6xCJkuUYttEEfA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "21.2.0", + "babel-plugin-syntax-object-rest-spread": "6.13.0" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "dev": true, + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "dev": true, + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.1", + "regenerator-runtime": "0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bit-twiddle": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz", + "integrity": "sha1-DGwfq+KyPRcXPZpht7cJPrnhdp4=" + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "blueimp-load-image": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/blueimp-load-image/-/blueimp-load-image-2.17.1.tgz", + "integrity": "sha512-kE6VA2rSBXbFAc9M9laaMD2oOssSopUwLPsjYlFDj4qLY5T1v9ieDi6rAon6fLKTYzlXbIEnxzyCYS/uD2U3NQ==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.1", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.15" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "2.1.1", + "deep-equal": "1.0.1", + "dns-equal": "1.0.0", + "dns-txt": "2.0.2", + "multicast-dns": "6.2.1", + "multicast-dns-service-types": "1.1.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.5" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "browserslist": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.9.1.tgz", + "integrity": "sha512-3n3nPdbUqn3nWmsy4PeSQthz2ja1ndpoXta+dwFFNhveGjMg6FXpWYe12vsTpNoXJbzx3j7GZXdtoVIdvh3JbA==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000777", + "electron-to-chromium": "1.3.27" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caniuse-api": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", + "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000777", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" + }, + "dependencies": { + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000777", + "electron-to-chromium": "1.3.27" + } + } + } + }, + "caniuse-db": { + "version": "1.0.30000777", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000777.tgz", + "integrity": "sha1-LhmtumO918UB32N6hirerX9LwFQ=", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30000777", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000777.tgz", + "integrity": "sha1-McGKSozUl4LrswXI6Kk+azs+TxM=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "chroma-js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-1.3.4.tgz", + "integrity": "sha1-k6fBnyh5YChcw/3rsgW46hoPBPk=", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "dev": true, + "requires": { + "chalk": "1.1.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + } + } + }, + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "requires": { + "q": "1.5.1" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "1.0.3", + "color-convert": "1.9.1", + "color-string": "0.3.0" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "colormin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", + "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", + "dev": true, + "requires": { + "color": "0.11.4", + "css-color-names": "0.0.4", + "has": "1.0.1" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compressible": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", + "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "compression": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.1.tgz", + "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "bytes": "3.0.0", + "compressible": "2.0.12", + "debug": "2.6.9", + "on-headers": "1.0.1", + "safe-buffer": "5.1.1", + "vary": "1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "consolidate": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", + "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", + "dev": true, + "requires": { + "bluebird": "3.5.1" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "dev": true + }, + "cosmiconfig": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", + "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", + "dev": true, + "requires": { + "is-directory": "0.3.1", + "js-yaml": "3.7.0", + "minimist": "1.2.0", + "object-assign": "4.1.1", + "os-homedir": "1.0.2", + "parse-json": "2.2.0", + "require-from-string": "1.2.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.9" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.5", + "randomfill": "1.0.3" + } + }, + "css-color-function": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/css-color-function/-/css-color-function-1.3.3.tgz", + "integrity": "sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4=", + "dev": true, + "requires": { + "balanced-match": "0.1.0", + "color": "0.11.4", + "debug": "3.1.0", + "rgb": "0.1.0" + }, + "dependencies": { + "balanced-match": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.1.0.tgz", + "integrity": "sha1-tQS9BYabOSWd0MXvw12EMXbczEo=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-loader": { + "version": "0.28.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.7.tgz", + "integrity": "sha512-GxMpax8a/VgcfRrVy0gXD6yLd5ePYbXX/5zGgTVYp4wXtJklS8Z2VaUArJgc//f6/Dzil7BaJObdSv8eKKCPgg==", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "css-selector-tokenizer": "0.7.0", + "cssnano": "3.10.0", + "icss-utils": "2.1.0", + "loader-utils": "1.1.0", + "lodash.camelcase": "4.3.0", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-modules-extract-imports": "1.1.0", + "postcss-modules-local-by-default": "1.2.0", + "postcss-modules-scope": "1.1.0", + "postcss-modules-values": "1.3.0", + "postcss-value-parser": "3.3.0", + "source-list-map": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "css-selector-tokenizer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", + "dev": true, + "requires": { + "cssesc": "0.1.0", + "fastparse": "1.1.1", + "regexpu-core": "1.0.0" + }, + "dependencies": { + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + } + } + }, + "css-unit-converter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", + "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", + "dev": true + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cssnano": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "dev": true, + "requires": { + "autoprefixer": "6.7.7", + "decamelize": "1.2.0", + "defined": "1.0.0", + "has": "1.0.1", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-calc": "5.3.1", + "postcss-colormin": "2.2.2", + "postcss-convert-values": "2.6.1", + "postcss-discard-comments": "2.0.4", + "postcss-discard-duplicates": "2.1.0", + "postcss-discard-empty": "2.1.0", + "postcss-discard-overridden": "0.1.1", + "postcss-discard-unused": "2.2.3", + "postcss-filter-plugins": "2.0.2", + "postcss-merge-idents": "2.1.7", + "postcss-merge-longhand": "2.0.2", + "postcss-merge-rules": "2.1.2", + "postcss-minify-font-values": "1.0.5", + "postcss-minify-gradients": "1.0.5", + "postcss-minify-params": "1.2.2", + "postcss-minify-selectors": "2.1.1", + "postcss-normalize-charset": "1.1.1", + "postcss-normalize-url": "3.0.8", + "postcss-ordered-values": "2.2.3", + "postcss-reduce-idents": "2.4.0", + "postcss-reduce-initial": "1.0.1", + "postcss-reduce-transforms": "1.0.4", + "postcss-svgo": "2.1.6", + "postcss-unique-selectors": "2.0.2", + "postcss-value-parser": "3.3.0", + "postcss-zindex": "2.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000777", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000777", + "electron-to-chromium": "1.3.27" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "csso": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", + "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", + "dev": true, + "requires": { + "clap": "1.2.3", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "cwise": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/cwise/-/cwise-1.0.10.tgz", + "integrity": "sha1-JO7mBy69/WuMb12tsXCQtkmxK+8=", + "requires": { + "cwise-compiler": "1.1.3", + "cwise-parser": "1.0.3", + "static-module": "1.5.0", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "requires": { + "uniq": "1.0.1" + } + }, + "cwise-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cwise-parser/-/cwise-parser-1.0.3.tgz", + "integrity": "sha1-jkk8F9VPl8sDCp6YVLyGyd+zVP4=", + "requires": { + "esprima": "1.2.5", + "uniq": "1.0.1" + }, + "dependencies": { + "esprima": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=" + } + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.37" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "6.1.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "p-map": "1.2.0", + "pify": "3.0.0", + "rimraf": "2.6.2" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "detect-node": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", + "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.5" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.2.2.tgz", + "integrity": "sha512-kN+DjfGF7dJGUL7nWRktL9Z18t1rWP3aQlyZdY8XlpvU3Nc6GeFTQApftcjtWKxAZfiggZSGrCEoszNgvnpwDg==", + "dev": true, + "requires": { + "ip": "1.1.5", + "safe-buffer": "5.1.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "1.1.1" + } + }, + "doctrine": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz", + "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==", + "dev": true, + "requires": { + "esutils": "2.0.2" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", + "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", + "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, + "dup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dup/-/dup-1.0.0.tgz", + "integrity": "sha1-UfxaxoX4GWRp3wuQXpNLIK9bQCk=" + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "ecstatic": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-2.2.1.tgz", + "integrity": "sha512-ztE4WqheoWLh3wv+HQwy7dACnvNY620coWpa+XqY6R2cVWgaAT2lUISU1Uf7JpdLLJCURktJOaA9av2AOzsyYQ==", + "dev": true, + "requires": { + "he": "1.1.1", + "mime": "1.3.6", + "minimist": "1.2.0", + "url-join": "2.0.2" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz", + "integrity": "sha1-eOy4o5kGYYe7N07t412ccFZagD0=", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", + "dev": true + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "errno": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "dev": true, + "requires": { + "prr": "0.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.37", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", + "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.12.1.tgz", + "integrity": "sha512-28hOYej+NZ/R5H1yMvyKa1+bPlu+fnsIAQffK6hxXgvmXnImos2bA5XfCn5dYv2k2mrKj+/U/Z4L5ICWxC7TQw==", + "dev": true, + "requires": { + "ajv": "5.5.0", + "babel-code-frame": "6.26.0", + "chalk": "2.3.0", + "concat-stream": "1.6.0", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.0.2", + "eslint-scope": "3.7.1", + "espree": "3.5.2", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", + "glob": "7.1.2", + "globals": "11.0.1", + "ignore": "3.3.7", + "imurmurhash": "0.1.4", + "inquirer": "3.3.0", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify-without-jsonify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "7.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "semver": "5.4.1", + "strip-ansi": "4.0.0", + "strip-json-comments": "2.0.1", + "table": "4.0.2", + "text-table": "0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "eslint-import-resolver-node": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz", + "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==", + "dev": true, + "requires": { + "debug": "2.6.9", + "resolve": "1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "eslint-loader": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-1.9.0.tgz", + "integrity": "sha512-40aN976qSNPyb9ejTqjEthZITpls1SVKtwguahmH1dzGCwQU/vySE+xX33VZmD8csU0ahVNCtFlsPgKqRBiqgg==", + "dev": true, + "requires": { + "loader-fs-cache": "1.0.1", + "loader-utils": "1.1.0", + "object-assign": "4.1.1", + "object-hash": "1.2.0", + "rimraf": "2.6.2" + } + }, + "eslint-module-utils": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "pkg-dir": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + } + } + }, + "eslint-plugin-html": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.1.tgz", + "integrity": "sha512-w8mmUJQjtDMUNbw3NOa4+PjOH/r4W5T+RN2nCmYgXv+QHx+NiBodnbPHXmJFJgo7Dr0Yk4G/2LCIRhfKceNmNA==", + "dev": true, + "requires": { + "htmlparser2": "3.9.2" + } + }, + "eslint-plugin-import": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", + "dev": true, + "requires": { + "builtin-modules": "1.1.1", + "contains-path": "0.1.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "0.3.1", + "eslint-module-utils": "2.1.1", + "has": "1.0.1", + "lodash.cond": "4.5.2", + "minimatch": "3.0.4", + "read-pkg-up": "2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "espree": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "dev": true, + "requires": { + "acorn": "5.2.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.37" + } + }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "eventsource": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", + "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "dev": true, + "requires": { + "original": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "express": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", + "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.1", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.0", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.2", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.1", + "serve-static": "1.13.1", + "setprototypeof": "1.1.0", + "statuses": "1.3.1", + "type-is": "1.6.15", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-text-webpack-plugin": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz", + "integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==", + "dev": true, + "requires": { + "async": "2.6.0", + "loader-utils": "1.1.0", + "schema-utils": "0.3.0", + "webpack-sources": "1.1.0" + } + }, + "falafel": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", + "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "requires": { + "acorn": "5.2.1", + "foreach": "2.0.5", + "isarray": "0.0.1", + "object-keys": "1.0.11" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastparse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "make-dir": "1.1.0", + "pkg-dir": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + }, + "dependencies": { + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", + "dev": true + }, + "follow-redirects": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.6.tgz", + "integrity": "sha512-FrMqZ/FONtHnbqO651UPpfRUVukIEwJhXMfdr/JWAmrDbeYBu773b1J6gdWDyRIj4hvvzQEHoEOTrdR8o6KLYA==", + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.2.tgz", + "integrity": "sha1-4fJE7zkzwbKmS9R5kTYGDQ9ZFPg=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.0.1.tgz", + "integrity": "sha1-Eqh7sBDlFUOWrMU14eQ/x1Ow5eg=", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "handle-thing": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "dev": true + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", + "dev": true + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "obuf": "1.1.1", + "readable-stream": "2.3.3", + "wbuf": "1.7.2" + } + }, + "html-comment-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", + "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", + "dev": true + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.4.1", + "domutils": "1.6.2", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + }, + "dependencies": { + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", + "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=", + "dev": true + }, + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", + "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", + "dev": true, + "requires": { + "http-proxy": "1.16.2", + "is-glob": "3.1.0", + "lodash": "4.17.4", + "micromatch": "2.3.11" + }, + "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "http-server": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.10.0.tgz", + "integrity": "sha1-sqRGsWqduH7TxiK6m+sbCFsSNKc=", + "dev": true, + "requires": { + "colors": "1.0.3", + "corser": "2.0.1", + "ecstatic": "2.2.1", + "http-proxy": "1.16.2", + "opener": "1.4.3", + "optimist": "0.6.1", + "portfinder": "1.0.13", + "union": "0.4.6" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + } + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "ignore": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", + "dev": true + }, + "import-local": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-0.1.1.tgz", + "integrity": "sha1-sReVcqrNwRxqkQCftDDbyrX2aKg=", + "dev": true, + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.1.0", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "internal-ip": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz", + "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", + "dev": true, + "requires": { + "meow": "3.7.0" + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ipaddr.js": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", + "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "dev": true, + "requires": { + "html-comment-regex": "1.1.1" + } + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isnumeric": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/isnumeric/-/isnumeric-0.2.0.tgz", + "integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz", + "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.9.1.tgz", + "integrity": "sha512-RQmXeQ7sphar7k7O1wTNzVczF9igKpaeGQAG9qR2L+BS4DCJNTI9nytRmIVYevwO0bbq+2CXvJmYDuz0gMrywA==", + "dev": true, + "requires": { + "babel-generator": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.1.1", + "semver": "5.4.1" + } + }, + "js-base64": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.0.tgz", + "integrity": "sha512-Wehd+7Pf9tFvGb+ydPm9TjYjV8X1YHOVyG8QyELZxEMqOhemVwGRmoG8iQ/soqI3n8v4xn59zaLxiCJiaaRzKA==", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "2.7.3" + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "killable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", + "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "loader-fs-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz", + "integrity": "sha1-VuC/CL2XCLJqdltoUJhAyN7J/bw=", + "dev": true, + "requires": { + "find-cache-dir": "0.1.1", + "mkdirp": "0.5.1" + }, + "dependencies": { + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "1.1.2" + } + } + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.cond": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", + "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.templatesettings": "4.1.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "loglevel": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.0.tgz", + "integrity": "sha1-rgyqVhERSYxboTcj1vtjHSQAOTQ=", + "dev": true + }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "macaddress": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", + "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", + "dev": true + }, + "make-dir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "dev": true, + "requires": { + "pify": "3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "math-expression-evaluator": { + "version": "1.2.17", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", + "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", + "dev": true + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.4", + "readable-stream": "2.3.3" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.6.tgz", + "integrity": "sha1-WR2E02U6awtKO5343lqoEI5y5eA=", + "dev": true + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multicast-dns": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.1.tgz", + "integrity": "sha512-uV3/ckdsffHx9IrGQrx613mturMdMqQ06WTq+C09NsStJ9iNG6RcUWgPKs1Rfjy+idZT6tfQoXEusGNnEZhT3w==", + "dev": true, + "requires": { + "dns-packet": "1.2.2", + "thunky": "0.1.0" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ndarray": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", + "requires": { + "iota-array": "1.0.0", + "is-buffer": "1.1.6" + } + }, + "ndarray-blas-level1": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ndarray-blas-level1/-/ndarray-blas-level1-1.1.3.tgz", + "integrity": "sha1-7BXPrO2BmH1lGgizcf+3u929eYI=" + }, + "ndarray-blas-level2": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ndarray-blas-level2/-/ndarray-blas-level2-1.1.0.tgz", + "integrity": "sha1-s6YUC5oj/qOg+KE6klwpzP6qzkw=", + "requires": { + "ndarray-blas-level1": "1.1.3" + } + }, + "ndarray-concat-rows": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-concat-rows/-/ndarray-concat-rows-1.0.1.tgz", + "integrity": "sha1-1/h3kmXvw6mniLsU4pf6Hh8CF8M=", + "requires": { + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0", + "util-extend": "1.0.3" + } + }, + "ndarray-fft": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-fft/-/ndarray-fft-1.0.3.tgz", + "integrity": "sha1-3Fu6GOOrgsmXrbrrt455+CyToio=", + "requires": { + "bit-twiddle": "1.0.2", + "cwise": "1.0.10", + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "ndarray-gemm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-gemm/-/ndarray-gemm-1.0.0.tgz", + "integrity": "sha1-POWbMc9eIkPIZfBpQ/e0cUz7se4=" + }, + "ndarray-ops": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ndarray-ops/-/ndarray-ops-1.2.2.tgz", + "integrity": "sha1-WeiNLDKn7ryxvGkPrhQVeVV6YU4=", + "requires": { + "cwise-compiler": "1.1.3" + } + }, + "ndarray-resample": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-resample/-/ndarray-resample-1.0.1.tgz", + "integrity": "sha1-Qrsz9qS3OMV/9zxgzCINTPx1gh0=", + "requires": { + "cwise": "1.0.10", + "ndarray-fft": "1.0.3", + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0" + } + }, + "ndarray-scratch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ndarray-scratch/-/ndarray-scratch-1.2.0.tgz", + "integrity": "sha1-YwRjbWLrqT20cnrBPGkzQdulDgE=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "ndarray-squeeze": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ndarray-squeeze/-/ndarray-squeeze-1.0.2.tgz", + "integrity": "sha1-diXGnGcMv0YHkuigEd6NBHKU02w=", + "requires": { + "ndarray": "1.0.18" + } + }, + "ndarray-tile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-tile/-/ndarray-tile-1.0.3.tgz", + "integrity": "sha1-eibjlGz43xieqTXHVnmB7Ma4IPo=", + "requires": { + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0" + } + }, + "ndarray-unpack": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-unpack/-/ndarray-unpack-1.0.0.tgz", + "integrity": "sha1-S1PHZzAKXjkJuLUiWrVcbohtkdw=", + "requires": { + "cwise": "1.0.10", + "dup": "1.0.0" + } + }, + "ndarray-unsqueeze": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-unsqueeze/-/ndarray-unsqueeze-1.0.3.tgz", + "integrity": "sha1-3DqNoZx7meukGYgDbeX88pPIqwg=", + "requires": { + "ndarray": "1.0.18" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "node-forge": { + "version": "0.6.33", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz", + "integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=", + "dev": true + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.1.7", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.3", + "stream-browserify": "2.0.1", + "stream-http": "2.7.2", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.4", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "prepend-http": "1.0.4", + "query-string": "4.3.4", + "sort-keys": "1.1.2" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.2.0.tgz", + "integrity": "sha512-smRWXzkvxw72VquyZ0wggySl7PFUtoDhvhpdwgESXxUrH7vVhhp9asfup1+rVLrhsl7L45Ee1Q/l5R2Ul4MwUg==", + "dev": true + }, + "object-inspect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-0.4.0.tgz", + "integrity": "sha1-9RV8EWwUVbJDsG7pdwM5LFrYn+w=" + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "obuf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz", + "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onecolor": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.0.5.tgz", + "integrity": "sha1-Nu/zIgE3nv3xGA+0ReUajiQl+fY=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "opener": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", + "dev": true + }, + "opn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", + "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", + "dev": true, + "requires": { + "is-wsl": "1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "original": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", + "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "dev": true, + "requires": { + "url-parse": "1.0.5" + }, + "dependencies": { + "url-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", + "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", + "dev": true, + "requires": { + "querystringify": "0.0.4", + "requires-port": "1.0.0" + } + } + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.2", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "path": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/path/-/path-0.11.14.tgz", + "integrity": "sha1-y8dWk1XLPIOv60rOQ+z/lSMeWn0=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pixrem": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pixrem/-/pixrem-4.0.1.tgz", + "integrity": "sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY=", + "dev": true, + "requires": { + "browserslist": "2.9.1", + "postcss": "6.0.14", + "reduce-css-calc": "1.3.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "2.1.0" + } + }, + "pleeease-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pleeease-filters/-/pleeease-filters-4.0.0.tgz", + "integrity": "sha1-ZjKy+wVkjSdY2GU4T7zteeHMrsc=", + "dev": true, + "requires": { + "onecolor": "3.0.5", + "postcss": "6.0.14" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "portfinder": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", + "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", + "dev": true, + "requires": { + "async": "1.5.2", + "debug": "2.6.9", + "mkdirp": "0.5.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "postcss": { + "version": "6.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.14.tgz", + "integrity": "sha512-NJ1z0f+1offCgadPhz+DvGm5Mkci+mmV5BqD13S992o0Xk9eElxUfPPF+t2ksH5R/17gz4xVK8KWocUQ5o3Rog==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "4.5.0" + } + }, + "postcss-apply": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/postcss-apply/-/postcss-apply-0.8.0.tgz", + "integrity": "sha1-FOVEu7XLbxweBIhXll15rgZrE0M=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "balanced-match": "0.4.2", + "postcss": "6.0.14" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "postcss-attribute-case-insensitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-2.0.0.tgz", + "integrity": "sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-selector-parser": "2.2.3" + } + }, + "postcss-calc": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-message-helpers": "2.0.0", + "reduce-css-calc": "1.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-color-function": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-function/-/postcss-color-function-4.0.1.tgz", + "integrity": "sha1-QCs/LOvD9pR+YY+2vjZU++zvZEQ=", + "dev": true, + "requires": { + "css-color-function": "1.3.3", + "postcss": "6.0.14", + "postcss-message-helpers": "2.0.0", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-color-gray": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-4.0.0.tgz", + "integrity": "sha1-aBvzBQl91mv+8OHmKC1dmbWsyV0=", + "dev": true, + "requires": { + "color": "1.0.3", + "postcss": "6.0.14", + "postcss-message-helpers": "2.0.0", + "reduce-function-call": "1.0.2" + }, + "dependencies": { + "color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", + "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", + "dev": true, + "requires": { + "color-convert": "1.9.1", + "color-string": "1.5.2" + } + }, + "color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", + "dev": true, + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + } + } + }, + "postcss-color-hex-alpha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-3.0.0.tgz", + "integrity": "sha1-HlPmyKyyN5Vej9CLfs2xuLgwn5U=", + "dev": true, + "requires": { + "color": "1.0.3", + "postcss": "6.0.14", + "postcss-message-helpers": "2.0.0" + }, + "dependencies": { + "color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", + "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", + "dev": true, + "requires": { + "color-convert": "1.9.1", + "color-string": "1.5.2" + } + }, + "color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", + "dev": true, + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + } + } + }, + "postcss-color-hsl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hsl/-/postcss-color-hsl-2.0.0.tgz", + "integrity": "sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-value-parser": "3.3.0", + "units-css": "0.4.0" + } + }, + "postcss-color-hwb": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-hwb/-/postcss-color-hwb-3.0.0.tgz", + "integrity": "sha1-NAKxnvTYSXVAwftQcr6YY8qVVx4=", + "dev": true, + "requires": { + "color": "1.0.3", + "postcss": "6.0.14", + "postcss-message-helpers": "2.0.0", + "reduce-function-call": "1.0.2" + }, + "dependencies": { + "color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-1.0.3.tgz", + "integrity": "sha1-5I6DLYXxTvaU+0aIEcLVz+cptV0=", + "dev": true, + "requires": { + "color-convert": "1.9.1", + "color-string": "1.5.2" + } + }, + "color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", + "dev": true, + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + } + } + }, + "postcss-color-rebeccapurple": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-3.0.0.tgz", + "integrity": "sha1-7rrwPTY7QwC5Z5K9MIHBntZlE9M=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-color-rgb": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rgb/-/postcss-color-rgb-2.0.0.tgz", + "integrity": "sha1-FFOcinExSUtILg3RzCZf9lFLUmM=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-color-rgba-fallback": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-3.0.0.tgz", + "integrity": "sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-value-parser": "3.3.0", + "rgb-hex": "2.1.0" + } + }, + "postcss-colormin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", + "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "dev": true, + "requires": { + "colormin": "1.1.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-convert-values": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", + "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-cssnext": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-cssnext/-/postcss-cssnext-3.0.2.tgz", + "integrity": "sha512-jA6kGdcUMZqLUgw6MdpyNWGFhk0LIITVhC/jTnLRZLoXSTR88qT2cFOn3LbY06udt1PVdTCHDG3plBjxVKf8BQ==", + "dev": true, + "requires": { + "autoprefixer": "7.1.6", + "caniuse-api": "2.0.0", + "chalk": "2.3.0", + "pixrem": "4.0.1", + "pleeease-filters": "4.0.0", + "postcss": "6.0.14", + "postcss-apply": "0.8.0", + "postcss-attribute-case-insensitive": "2.0.0", + "postcss-calc": "6.0.1", + "postcss-color-function": "4.0.1", + "postcss-color-gray": "4.0.0", + "postcss-color-hex-alpha": "3.0.0", + "postcss-color-hsl": "2.0.0", + "postcss-color-hwb": "3.0.0", + "postcss-color-rebeccapurple": "3.0.0", + "postcss-color-rgb": "2.0.0", + "postcss-color-rgba-fallback": "3.0.0", + "postcss-custom-media": "6.0.0", + "postcss-custom-properties": "6.2.0", + "postcss-custom-selectors": "4.0.1", + "postcss-font-family-system-ui": "2.1.1", + "postcss-font-variant": "3.0.0", + "postcss-image-set-polyfill": "0.3.5", + "postcss-initial": "2.0.0", + "postcss-media-minmax": "3.0.0", + "postcss-nesting": "4.2.1", + "postcss-pseudo-class-any-link": "4.0.0", + "postcss-pseudoelements": "5.0.0", + "postcss-replace-overflow-wrap": "2.0.0", + "postcss-selector-matches": "3.0.1", + "postcss-selector-not": "3.0.1" + }, + "dependencies": { + "caniuse-api": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-2.0.0.tgz", + "integrity": "sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ=", + "dev": true, + "requires": { + "browserslist": "2.9.1", + "caniuse-lite": "1.0.30000777", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" + } + }, + "postcss-calc": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-6.0.1.tgz", + "integrity": "sha1-PSQXG79udinUIqQ26/5t2VEfQzA=", + "dev": true, + "requires": { + "css-unit-converter": "1.1.1", + "postcss": "6.0.14", + "postcss-selector-parser": "2.2.3", + "reduce-css-calc": "2.1.3" + } + }, + "reduce-css-calc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.3.tgz", + "integrity": "sha1-Y8TGMl/7v06mwj8dTetHw5U/O4E=", + "dev": true, + "requires": { + "css-unit-converter": "1.1.1", + "postcss-value-parser": "3.3.0" + } + } + } + }, + "postcss-custom-media": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-6.0.0.tgz", + "integrity": "sha1-vlMnhBEOyylQRPtTlaGABushpzc=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-custom-properties": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz", + "integrity": "sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "postcss": "6.0.14" + } + }, + "postcss-custom-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-4.0.1.tgz", + "integrity": "sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-selector-matches": "3.0.1" + } + }, + "postcss-discard-comments": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-duplicates": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", + "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-empty": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-overridden": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-unused": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "uniqs": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-filter-plugins": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", + "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "uniqid": "4.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-font-family-system-ui": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-font-family-system-ui/-/postcss-font-family-system-ui-2.1.1.tgz", + "integrity": "sha512-AOAn553wVmMDx2nph0axVDXJwhsd9x4MjKHRH9SOXL4YdiqsYFxyTVTWnlka9iNB70Pb3Idxmj79bIXxq38b/w==", + "dev": true, + "requires": { + "@std/esm": "0.16.0", + "lodash": "4.17.4", + "postcss": "6.0.14", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-font-variant": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-3.0.0.tgz", + "integrity": "sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-image-set-polyfill": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/postcss-image-set-polyfill/-/postcss-image-set-polyfill-0.3.5.tgz", + "integrity": "sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-media-query-parser": "0.2.3" + } + }, + "postcss-import": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.0.0.tgz", + "integrity": "sha1-qWLi34LTvFptpqOGhBdHIE9B71s=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-value-parser": "3.3.0", + "read-cache": "1.0.0", + "resolve": "1.5.0" + } + }, + "postcss-initial": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-2.0.0.tgz", + "integrity": "sha1-cnFfczbgu3k1HZnuZcSiU6hEG6Q=", + "dev": true, + "requires": { + "lodash.template": "4.4.0", + "postcss": "6.0.14" + } + }, + "postcss-load-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", + "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", + "dev": true, + "requires": { + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1", + "postcss-load-options": "1.2.0", + "postcss-load-plugins": "2.3.0" + } + }, + "postcss-load-options": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", + "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", + "dev": true, + "requires": { + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" + } + }, + "postcss-load-plugins": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", + "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", + "dev": true, + "requires": { + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" + } + }, + "postcss-loader": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.0.9.tgz", + "integrity": "sha512-sgoXPtmgVT3aBAhU47Kig8oPF+mbXl8Unjvtz1Qj1q2D2EvSVJW2mKJNzxv5y/LvA9xWwuvdysvhc7Zn80UWWw==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "postcss": "6.0.14", + "postcss-load-config": "1.2.0", + "schema-utils": "0.3.0" + } + }, + "postcss-media-minmax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-3.0.0.tgz", + "integrity": "sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "postcss-merge-idents": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", + "dev": true, + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-merge-longhand": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", + "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-merge-rules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", + "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-api": "1.6.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3", + "vendors": "1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000777", + "electron-to-chromium": "1.3.27" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-message-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", + "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", + "dev": true + }, + "postcss-minify-font-values": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-minify-params": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "uniqs": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-minify-selectors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", + "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true, + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.14" + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true, + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.14" + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true, + "requires": { + "icss-replace-symbols": "1.1.0", + "postcss": "6.0.14" + } + }, + "postcss-nesting": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-4.2.1.tgz", + "integrity": "sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA==", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-normalize-charset": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-normalize-url": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", + "dev": true, + "requires": { + "is-absolute-url": "2.1.0", + "normalize-url": "1.9.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-ordered-values": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", + "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-pseudo-class-any-link": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-4.0.0.tgz", + "integrity": "sha1-kVKgYT00UHIFE+iJKFS65C0O5o4=", + "dev": true, + "requires": { + "postcss": "6.0.14", + "postcss-selector-parser": "2.2.3" + } + }, + "postcss-pseudoelements": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudoelements/-/postcss-pseudoelements-5.0.0.tgz", + "integrity": "sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-reduce-idents": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-reduce-initial": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-reduce-transforms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", + "dev": true, + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-replace-overflow-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-2.0.0.tgz", + "integrity": "sha1-eU22+qVPjbEAhUOSqTr0V2i04ls=", + "dev": true, + "requires": { + "postcss": "6.0.14" + } + }, + "postcss-selector-matches": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-3.0.1.tgz", + "integrity": "sha1-5WNAEeE5UIgYYbvdWMLQER/8lqs=", + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "postcss": "6.0.14" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "postcss-selector-not": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-3.0.1.tgz", + "integrity": "sha1-Lk2y8JZTNsAefOx9tsYN/3ZzNdk=", + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "postcss": "6.0.14" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" + } + }, + "postcss-svgo": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", + "dev": true, + "requires": { + "is-svg": "2.1.0", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "svgo": "0.7.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-unique-selectors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "uniqs": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "dev": true + }, + "postcss-zindex": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", + "dev": true, + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "uniqs": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.0", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "prettier": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.8.2.tgz", + "integrity": "sha512-fHWjCwoRZgjP1rvLP7OGqOznq7xH1sHMQUFLX8qLRO79hI57+6xbc5vB904LxEkCfgFgyr3vv06JkafgCSzoZg==", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "protobufjs": { + "version": "6.8.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.3.tgz", + "integrity": "sha512-/iQhTYnSniRNmdRF9Kvw8odMSokwNOWVDOmMJjW64+EVE6igcdj/82Op/4MJ/WimgMRNac7gChlSVX4Gep/tHg==", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/base64": "1.1.2", + "@protobufjs/codegen": "2.0.4", + "@protobufjs/eventemitter": "1.1.0", + "@protobufjs/fetch": "1.1.0", + "@protobufjs/float": "1.0.2", + "@protobufjs/inquire": "1.1.0", + "@protobufjs/path": "1.1.2", + "@protobufjs/pool": "1.1.0", + "@protobufjs/utf8": "1.1.0", + "@types/long": "3.0.32", + "@types/node": "8.0.54", + "long": "3.2.0" + } + }, + "proxy-addr": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", + "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "dev": true, + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.5.2" + } + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.5" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", + "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", + "dev": true + }, + "quote-stream": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-0.0.0.tgz", + "integrity": "sha1-zeKelMQJsW4Z3HCYuJtmWPlyHTs=", + "requires": { + "minimist": "0.0.8", + "through2": "0.4.2" + } + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", + "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "dev": true, + "requires": { + "randombytes": "2.0.5", + "safe-buffer": "5.1.1" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "math-expression-evaluator": "1.2.17", + "reduce-function-call": "1.0.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "reduce-function-call": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", + "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", + "dev": true, + "requires": { + "balanced-match": "0.4.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "rgb": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rgb/-/rgb-0.1.0.tgz", + "integrity": "sha1-vieykej+/+rBvZlylyG/pA/AN7U=", + "dev": true + }, + "rgb-hex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-2.1.0.tgz", + "integrity": "sha1-x3PF/iJoolV42SU5qCp6XOU77aY=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.1.tgz", + "integrity": "sha1-v4y3uDJWxFUeMTR8YxF3jbme7FI=", + "dev": true, + "requires": { + "node-forge": "0.6.33" + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "send": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", + "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "1.1.1", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "1.0.3", + "http-errors": "1.6.2", + "mime-types": "2.1.17", + "parseurl": "1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "serve-static": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", + "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "dev": true, + "requires": { + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz", + "integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0=", + "dev": true + } + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "sockjs": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.18.tgz", + "integrity": "sha1-2bKJMWyn33dZXvKZ4HXw+TfrQgc=", + "dev": true, + "requires": { + "faye-websocket": "0.10.0", + "uuid": "2.0.3" + } + }, + "sockjs-client": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", + "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "eventsource": "0.1.6", + "faye-websocket": "0.11.1", + "inherits": "2.0.3", + "json3": "3.3.2", + "url-parse": "1.2.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + } + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "spdy": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", + "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "dev": true, + "requires": { + "debug": "2.6.9", + "handle-thing": "1.2.5", + "http-deceiver": "1.2.7", + "safe-buffer": "5.1.1", + "select-hose": "2.0.0", + "spdy-transport": "2.0.20" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "spdy-transport": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz", + "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=", + "dev": true, + "requires": { + "debug": "2.6.9", + "detect-node": "2.0.3", + "hpack.js": "2.1.6", + "obuf": "1.1.1", + "readable-stream": "2.3.3", + "safe-buffer": "5.1.1", + "wbuf": "1.7.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "static-eval": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-0.2.4.tgz", + "integrity": "sha1-t9NNg4k3uWn5ZBygfUj47eJj6ns=", + "requires": { + "escodegen": "0.0.28" + }, + "dependencies": { + "escodegen": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.28.tgz", + "integrity": "sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=", + "requires": { + "esprima": "1.0.4", + "estraverse": "1.3.2", + "source-map": "0.6.1" + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + }, + "estraverse": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", + "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=" + } + } + }, + "static-module": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-1.5.0.tgz", + "integrity": "sha1-J9qYg8QajNCSNvhC8MHrxu32PYY=", + "requires": { + "concat-stream": "1.6.0", + "duplexer2": "0.0.2", + "escodegen": "1.3.3", + "falafel": "2.1.0", + "has": "1.0.1", + "object-inspect": "0.4.0", + "quote-stream": "0.0.0", + "readable-stream": "1.0.34", + "shallow-copy": "0.0.1", + "static-eval": "0.2.4", + "through2": "0.4.2" + }, + "dependencies": { + "escodegen": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", + "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", + "requires": { + "esprima": "1.1.1", + "estraverse": "1.5.1", + "esutils": "1.0.0", + "source-map": "0.1.43" + } + }, + "esprima": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", + "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" + }, + "estraverse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" + }, + "esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "stream-http": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "style-loader": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.19.0.tgz", + "integrity": "sha512-9mx9sC9nX1dgP96MZOODpGC6l1RzQBITI2D5WJhu+wnbrSYVKLGuy14XJSLVQih/0GFrPpjelt+s//VcZQ2Evw==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "schema-utils": "0.3.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", + "dev": true, + "requires": { + "coa": "1.0.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.4", + "whet.extend": "0.9.9" + } + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "5.5.0", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", + "lodash": "4.17.4", + "slice-ansi": "1.0.0", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "test-exclude": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.1.1.tgz", + "integrity": "sha512-35+Asrsk3XHJDBgf/VRFexPgh3UyETv8IAn/LRTiZjVy6rjPVqdEk8dJcJYBzl1w0XCJM48lvTy8SfEsCWS4nA==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "micromatch": "2.3.11", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "thunky": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-0.1.0.tgz", + "integrity": "sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=", + "dev": true + }, + "time-stamp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", + "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", + "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.17" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typedarray-pool/-/typedarray-pool-1.1.0.tgz", + "integrity": "sha1-0RT0hIAUifU+yrXoCIqiMET0mNk=", + "requires": { + "bit-twiddle": "1.0.2", + "dup": "1.0.0" + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "union": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", + "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", + "dev": true, + "requires": { + "qs": "2.3.3" + }, + "dependencies": { + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "uniqid": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", + "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", + "dev": true, + "requires": { + "macaddress": "0.2.8" + } + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "units-css": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/units-css/-/units-css-0.4.0.tgz", + "integrity": "sha1-1iKGU6UZg9fBb/KPi53Dsf/tOgc=", + "dev": true, + "requires": { + "isnumeric": "0.2.0", + "viewport-dimensions": "0.2.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-join": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.2.tgz", + "integrity": "sha1-wHJ1aWetJLi1nldBVRyqx49QuLc=", + "dev": true + }, + "url-loader": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.6.2.tgz", + "integrity": "sha512-h3qf9TNn53BpuXTTcpC+UehiRrl0Cv45Yr/xWayApjw6G8Bg2dGke7rIwDQ39piciWCWrC+WiqLjOh3SUp9n0Q==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "mime": "1.6.0", + "schema-utils": "0.3.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + } + } + }, + "url-parse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", + "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", + "dev": true, + "requires": { + "querystringify": "1.0.0", + "requires-port": "1.0.0" + }, + "dependencies": { + "querystringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", + "dev": true + } + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", + "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=", + "dev": true + }, + "viewport-dimensions": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz", + "integrity": "sha1-3nQHR9tTh/0XJfUXXpG6x2r982w=", + "dev": true + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "vue": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.9.tgz", + "integrity": "sha512-9B9XBpCtj8y5eJFrspIcKxIWt+lG9FMdF8qgyOlUeOIvcS4xSAvcARygbzHA6Pi0KWFj4BvxjtWbuPVWRx/wuA==", + "dev": true + }, + "vue-hot-reload-api": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.2.4.tgz", + "integrity": "sha512-e+ThJMYmZg4D9UnrLcr6LQxGu6YlcxkrmZGPCyIN4malcNhdeGGKxmFuM5y6ICMJJxQywLfT8MM1rYZr4LpeLw==", + "dev": true + }, + "vue-loader": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-13.5.0.tgz", + "integrity": "sha512-O0+ZU1oyLlDXSAQB7pV/pwVt3wJLfyhXtnGpCVFBGMKGC0Yp9Un7ULFHKejrFEYaMBKY0s6h4iJzjMdSngNA2g==", + "dev": true, + "requires": { + "consolidate": "0.14.5", + "hash-sum": "1.0.2", + "loader-utils": "1.1.0", + "lru-cache": "4.1.1", + "postcss": "6.0.14", + "postcss-load-config": "1.2.0", + "postcss-selector-parser": "2.2.3", + "prettier": "1.8.2", + "resolve": "1.5.0", + "source-map": "0.6.1", + "vue-hot-reload-api": "2.2.4", + "vue-style-loader": "3.0.3", + "vue-template-es2015-compiler": "1.6.0" + } + }, + "vue-router": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.1.tgz", + "integrity": "sha512-vLLoY452L+JBpALMP5UHum9+7nzR9PeIBCghU9ZtJ1eWm6ieUI8Zb/DI3MYxH32bxkjzYV1LRjNv4qr8d+uX/w==", + "dev": true + }, + "vue-style-loader": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-3.0.3.tgz", + "integrity": "sha512-P/ihpaZKU23T1kq3E0y4c+F8sbm1HQO69EFYoLoGMSGVAHroHsGir/WQ9qUavP8dyFYHmXenzHaJ/nqd8vfaxw==", + "dev": true, + "requires": { + "hash-sum": "1.0.2", + "loader-utils": "1.1.0" + } + }, + "vue-template-compiler": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.9.tgz", + "integrity": "sha512-Icev7QPuQ3flpOvxMe09irgXPklBi/VpiveUDs5nRVH5GA8R9asLBlahsA7AuRZQbaty0cGKm6kh/icDLcr93w==", + "dev": true, + "requires": { + "de-indent": "1.0.2", + "he": "1.1.1" + } + }, + "vue-template-es2015-compiler": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz", + "integrity": "sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==", + "dev": true + }, + "vuetify": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-0.17.3.tgz", + "integrity": "sha512-oaq5KQsQNxYn559vBmbQmROX/yHEUcrQHkpNfmLlAhTJmRdrB6ky2CZbvQ6YC/kRrZ5Past3Nddd5oBVViEkhA==", + "dev": true + }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + } + }, + "wbuf": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz", + "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=", + "dev": true, + "requires": { + "minimalistic-assert": "1.0.0" + } + }, + "webpack": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.9.1.tgz", + "integrity": "sha512-jONJ0l8nqgiQVkqs15O9TFWLozbFkCgVodVrBXBK/PIBFeGkaOGo30Ov57iQqYRwAWNDM5vyLPZYmAIpPa5QSw==", + "dev": true, + "requires": { + "acorn": "5.2.1", + "acorn-dynamic-import": "2.0.2", + "ajv": "5.5.0", + "ajv-keywords": "2.1.1", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "dev": true, + "requires": { + "memory-fs": "0.4.1", + "mime": "1.6.0", + "path-is-absolute": "1.0.1", + "range-parser": "1.2.0", + "time-stamp": "2.0.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.9.5.tgz", + "integrity": "sha512-o0lS6enIxyOPiRJTh8vcgK5TsGNTn7lH1q/pNniAgs46mCE8sQYeqv7Y/oAIh/+u4kiBsFizLJo5EWC+ezz6FQ==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "array-includes": "3.0.3", + "bonjour": "3.5.0", + "chokidar": "1.7.0", + "compression": "1.7.1", + "connect-history-api-fallback": "1.5.0", + "debug": "3.1.0", + "del": "3.0.0", + "express": "4.16.2", + "html-entities": "1.2.1", + "http-proxy-middleware": "0.17.4", + "import-local": "0.1.1", + "internal-ip": "1.2.0", + "ip": "1.1.5", + "killable": "1.0.0", + "loglevel": "1.6.0", + "opn": "5.1.0", + "portfinder": "1.0.13", + "selfsigned": "1.10.1", + "serve-index": "1.9.1", + "sockjs": "0.3.18", + "sockjs-client": "1.1.4", + "spdy": "3.4.7", + "strip-ansi": "3.0.1", + "supports-color": "4.5.0", + "webpack-dev-middleware": "1.12.2", + "yargs": "6.6.0" + } + }, + "webpack-glsl-loader": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/webpack-glsl-loader/-/webpack-glsl-loader-1.0.1.tgz", + "integrity": "sha1-cqDjAZK9V5R9YNbVBckVvmgNCsw=", + "dev": true, + "requires": { + "fs": "0.0.2", + "path": "0.11.14" + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": "0.4.9", + "websocket-extensions": "0.1.3" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "4.2.1" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + } + } +} diff --git a/myproj/package-win32.json b/myproj/package-win32.json new file mode 100644 index 0000000000..dffa322698 --- /dev/null +++ b/myproj/package-win32.json @@ -0,0 +1,76 @@ +{ + "name": "myproj", + "version": "1.0.0", + "description": "A Vue.js project", + "author": "Bruce Lao", + "private": true, + "scripts": { + "build": "(npm install -g webpack webpack-dev-server) &(IF EXIST dist (rmdir /s /q dist)) & mkdir dist & (copy \/y external\\*.* dist\\) & (SET NODE_ENV=production; BABEL_ENV=browser) & webpack --config webpack.config.js", + "server": "(SET NODE_ENV=production; BABEL_ENV=browser) & webpack-dev-server --inline --progress --config webpack.config.js", + "unit": "jest --config test/unit/jest.conf.js --coverage", + "e2e": "node test/e2e/runner.js", + "test": "npm run unit && npm run e2e" + }, + "dependencies": { + "@babel/polyfill": "7.0.0-beta.32", + "axios": "^0.17.1", + "bluebird": "^3.5.1", + "cwise": "^1.0.10", + "lodash": "^4.17.4", + "ndarray": "^1.0.18", + "ndarray-blas-level2": "^1.1.0", + "ndarray-concat-rows": "^1.0.1", + "ndarray-gemm": "^1.0.0", + "ndarray-ops": "^1.2.2", + "ndarray-resample": "^1.0.1", + "ndarray-squeeze": "^1.0.2", + "ndarray-tile": "^1.0.3", + "ndarray-unpack": "^1.0.0", + "ndarray-unsqueeze": "^1.0.3", + "performance-now": "^2.1.0", + "protobufjs": "^6.8.1" + }, + "devDependencies": { + "babel-core": "^6.22.1", + "babel-eslint": "^7.1.1", + "babel-jest": "^21.0.2", + "babel-loader": "^7.1.1", + "babel-plugin-dynamic-import-node": "^1.2.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", + "babel-plugin-transform-runtime": "^6.22.0", + "babel-preset-env": "^1.3.2", + "babel-preset-stage-2": "^6.22.0", + "babel-register": "^6.22.0", + "blueimp-load-image": "^2.17.1", + "chroma-js": "^1.3.4", + "css-loader": "^0.28.7", + "eslint": "^4.12.0", + "eslint-loader": "^1.9.0", + "eslint-plugin-html": "^4.0.1", + "eslint-plugin-import": "^2.7.0", + "extract-text-webpack-plugin": "^3.0.2", + "http-server": "^0.10.0", + "postcss-cssnext": "^3.0.2", + "postcss-import": "^11.0.0", + "postcss-loader": "^2.0.9", + "style-loader": "^0.19.0", + "url-loader": "^0.6.2", + "vue": "^2.5.9", + "vue-loader": "^13.5.0", + "vue-router": "^3.0.1", + "vue-template-compiler": "^2.5.9", + "vuetify": "^0.17.3", + "webpack": "^3.8.1", + "webpack-dev-server": "^2.9.5", + "webpack-glsl-loader": "^1.0.1" + }, + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" + ] +} diff --git a/myproj/package.json b/myproj/package.json new file mode 100644 index 0000000000..1d2e230840 --- /dev/null +++ b/myproj/package.json @@ -0,0 +1,76 @@ +{ + "name": "myproj", + "version": "1.0.0", + "description": "A Vue.js project", + "author": "Bruce Lao", + "private": true, + "scripts": { + "build": "rm -rf dist; mkdir dist; cp external/* dist/; NODE_ENV=production BABEL_ENV=browser webpack --config webpack.config.js", + "server": "NODE_ENV=production BABEL_ENV=browser; webpack-dev-server --inline --progress --config webpack.config.js", + "unit": "jest --config test/unit/jest.conf.js --coverage", + "e2e": "node test/e2e/runner.js", + "test": "npm run unit && npm run e2e" + }, + "dependencies": { + "@babel/polyfill": "7.0.0-beta.32", + "axios": "^0.17.1", + "bluebird": "^3.5.1", + "cwise": "^1.0.10", + "lodash": "^4.17.4", + "ndarray": "^1.0.18", + "ndarray-blas-level2": "^1.1.0", + "ndarray-concat-rows": "^1.0.1", + "ndarray-gemm": "^1.0.0", + "ndarray-ops": "^1.2.2", + "ndarray-resample": "^1.0.1", + "ndarray-squeeze": "^1.0.2", + "ndarray-tile": "^1.0.3", + "ndarray-unpack": "^1.0.0", + "ndarray-unsqueeze": "^1.0.3", + "performance-now": "^2.1.0", + "protobufjs": "^6.8.1" + }, + "devDependencies": { + "babel-core": "^6.22.1", + "babel-eslint": "^7.1.1", + "babel-jest": "^21.0.2", + "babel-loader": "^7.1.1", + "babel-plugin-dynamic-import-node": "^1.2.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", + "babel-plugin-transform-runtime": "^6.22.0", + "babel-preset-env": "^1.3.2", + "babel-preset-stage-2": "^6.22.0", + "babel-register": "^6.22.0", + "blueimp-load-image": "^2.17.1", + "chroma-js": "^1.3.4", + "css-loader": "^0.28.7", + "eslint": "^4.12.0", + "eslint-loader": "^1.9.0", + "eslint-plugin-html": "^4.0.1", + "eslint-plugin-import": "^2.7.0", + "extract-text-webpack-plugin": "^3.0.2", + "http-server": "^0.10.0", + "postcss-cssnext": "^3.0.2", + "postcss-import": "^11.0.0", + "postcss-loader": "^2.0.9", + "style-loader": "^0.19.0", + "url-loader": "^0.6.2", + "vue": "^2.5.9", + "vue-loader": "^13.5.0", + "vue-router": "^3.0.1", + "vue-template-compiler": "^2.5.9", + "vuetify": "^0.17.3", + "webpack": "^3.8.1", + "webpack-dev-server": "^2.9.5", + "webpack-glsl-loader": "^1.0.1" + }, + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + }, + "browserslist": [ + "> 1%", + "last 2 versions", + "not ie <= 8" + ] +} diff --git a/myproj/src/App.vue b/myproj/src/App.vue new file mode 100644 index 0000000000..a73a874aff --- /dev/null +++ b/myproj/src/App.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/myproj/src/assets/imdb-bidirectional-lstm.png b/myproj/src/assets/imdb-bidirectional-lstm.png new file mode 100644 index 0000000000..7f6155ae74 Binary files /dev/null and b/myproj/src/assets/imdb-bidirectional-lstm.png differ diff --git a/myproj/src/assets/inception-v3.png b/myproj/src/assets/inception-v3.png new file mode 100644 index 0000000000..e736f8479a Binary files /dev/null and b/myproj/src/assets/inception-v3.png differ diff --git a/myproj/src/assets/logo-V.png b/myproj/src/assets/logo-V.png new file mode 100644 index 0000000000..f3d2503fc2 Binary files /dev/null and b/myproj/src/assets/logo-V.png differ diff --git a/myproj/src/assets/logo.png b/myproj/src/assets/logo.png new file mode 100644 index 0000000000..f0f1ee53be Binary files /dev/null and b/myproj/src/assets/logo.png differ diff --git a/myproj/src/assets/logo.svg b/myproj/src/assets/logo.svg new file mode 100644 index 0000000000..59b30746cd --- /dev/null +++ b/myproj/src/assets/logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/myproj/src/assets/mnist-acgan.png b/myproj/src/assets/mnist-acgan.png new file mode 100644 index 0000000000..03ec77da80 Binary files /dev/null and b/myproj/src/assets/mnist-acgan.png differ diff --git a/myproj/src/assets/mnist-cnn.png b/myproj/src/assets/mnist-cnn.png new file mode 100644 index 0000000000..ce33fd6c7f Binary files /dev/null and b/myproj/src/assets/mnist-cnn.png differ diff --git a/myproj/src/assets/mnist-vae.png b/myproj/src/assets/mnist-vae.png new file mode 100644 index 0000000000..583993ca4e Binary files /dev/null and b/myproj/src/assets/mnist-vae.png differ diff --git a/myproj/src/assets/resnet50.png b/myproj/src/assets/resnet50.png new file mode 100644 index 0000000000..b4116d753a Binary files /dev/null and b/myproj/src/assets/resnet50.png differ diff --git a/myproj/src/assets/squeezenet-v1.1.png b/myproj/src/assets/squeezenet-v1.1.png new file mode 100644 index 0000000000..2f036b33e7 Binary files /dev/null and b/myproj/src/assets/squeezenet-v1.1.png differ diff --git a/myproj/src/components/Home.vue b/myproj/src/components/Home.vue new file mode 100644 index 0000000000..440177fcef --- /dev/null +++ b/myproj/src/components/Home.vue @@ -0,0 +1,75 @@ + + + + + \ No newline at end of file diff --git a/myproj/src/components/NavDrawer.vue b/myproj/src/components/NavDrawer.vue new file mode 100644 index 0000000000..e421a42205 --- /dev/null +++ b/myproj/src/components/NavDrawer.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/myproj/src/components/models/HelloWorld.vue b/myproj/src/components/models/HelloWorld.vue new file mode 100644 index 0000000000..7c17dd64c7 --- /dev/null +++ b/myproj/src/components/models/HelloWorld.vue @@ -0,0 +1,50 @@ + + + + + + diff --git a/myproj/src/components/models/MnistCnn.vue b/myproj/src/components/models/MnistCnn.vue new file mode 100644 index 0000000000..95b21d8296 --- /dev/null +++ b/myproj/src/components/models/MnistCnn.vue @@ -0,0 +1,475 @@ + + + + + diff --git a/myproj/src/data/DemoModels.js b/myproj/src/data/DemoModels.js new file mode 100644 index 0000000000..0363ab888c --- /dev/null +++ b/myproj/src/data/DemoModels.js @@ -0,0 +1,3 @@ +export const DemoModelsDictionary = { + 'mnist-cnn': 'Basic Convnet for MNIST' +} \ No newline at end of file diff --git a/myproj/src/main.js b/myproj/src/main.js new file mode 100644 index 0000000000..6b7906f2a5 --- /dev/null +++ b/myproj/src/main.js @@ -0,0 +1,30 @@ +// The Vue build version to load with the `import` command +// (runtime-only or standalone) has been set in webpack.base.conf with an alias. +import Vue from 'vue' +import App from './App' +import router from './router' +import Vuetify from 'vuetify' +import 'vuetify/dist/vuetify.min.css' + +Vue.config.productionTip = false + +Vue.use(Vuetify, { + theme: { + primary: '#1bbc9b', + secondary: '#69707a', + accent: '#f5d76e', + error: '#d24d57' + } +}) + +// /* eslint-disable no-new */ +// new Vue({ +// el: '#root', +// router, +// template: '', // this App2 is the same as next line App2 +// components: { App2 } +// }) + +const app = new Vue(Object.assign({ router }, App)) + +app.$mount('#root') diff --git a/myproj/src/router/index.js b/myproj/src/router/index.js new file mode 100644 index 0000000000..7bb2706f1d --- /dev/null +++ b/myproj/src/router/index.js @@ -0,0 +1,18 @@ +import Vue from 'vue' +import Router from 'vue-router' +import Home from '../components/Home' +import HelloWorld from '../components/models/HelloWorld' +import MnistCnn from '../components/models/MnistCnn' + +Vue.use(Router) + +const routes = new Router({ + routes: [ + { path: '/', name: 'Home', component: Home }, + { path: '/home', name: 'Home', component: Home }, + { path: '/hello-world', name: 'HelloWorld', component: HelloWorld }, + { path: '/mnist-cnn', component: MnistCnn } + ] +}) + +export default routes diff --git a/myproj/src/utils/imagenet.js b/myproj/src/utils/imagenet.js new file mode 100644 index 0000000000..b51b468d55 --- /dev/null +++ b/myproj/src/utils/imagenet.js @@ -0,0 +1,1002 @@ +export const imagenetClasses = { + '0': ['n01440764', 'tench'], + '1': ['n01443537', 'goldfish'], + '2': ['n01484850', 'great_white_shark'], + '3': ['n01491361', 'tiger_shark'], + '4': ['n01494475', 'hammerhead'], + '5': ['n01496331', 'electric_ray'], + '6': ['n01498041', 'stingray'], + '7': ['n01514668', 'cock'], + '8': ['n01514859', 'hen'], + '9': ['n01518878', 'ostrich'], + '10': ['n01530575', 'brambling'], + '11': ['n01531178', 'goldfinch'], + '12': ['n01532829', 'house_finch'], + '13': ['n01534433', 'junco'], + '14': ['n01537544', 'indigo_bunting'], + '15': ['n01558993', 'robin'], + '16': ['n01560419', 'bulbul'], + '17': ['n01580077', 'jay'], + '18': ['n01582220', 'magpie'], + '19': ['n01592084', 'chickadee'], + '20': ['n01601694', 'water_ouzel'], + '21': ['n01608432', 'kite'], + '22': ['n01614925', 'bald_eagle'], + '23': ['n01616318', 'vulture'], + '24': ['n01622779', 'great_grey_owl'], + '25': ['n01629819', 'European_fire_salamander'], + '26': ['n01630670', 'common_newt'], + '27': ['n01631663', 'eft'], + '28': ['n01632458', 'spotted_salamander'], + '29': ['n01632777', 'axolotl'], + '30': ['n01641577', 'bullfrog'], + '31': ['n01644373', 'tree_frog'], + '32': ['n01644900', 'tailed_frog'], + '33': ['n01664065', 'loggerhead'], + '34': ['n01665541', 'leatherback_turtle'], + '35': ['n01667114', 'mud_turtle'], + '36': ['n01667778', 'terrapin'], + '37': ['n01669191', 'box_turtle'], + '38': ['n01675722', 'banded_gecko'], + '39': ['n01677366', 'common_iguana'], + '40': ['n01682714', 'American_chameleon'], + '41': ['n01685808', 'whiptail'], + '42': ['n01687978', 'agama'], + '43': ['n01688243', 'frilled_lizard'], + '44': ['n01689811', 'alligator_lizard'], + '45': ['n01692333', 'Gila_monster'], + '46': ['n01693334', 'green_lizard'], + '47': ['n01694178', 'African_chameleon'], + '48': ['n01695060', 'Komodo_dragon'], + '49': ['n01697457', 'African_crocodile'], + '50': ['n01698640', 'American_alligator'], + '51': ['n01704323', 'triceratops'], + '52': ['n01728572', 'thunder_snake'], + '53': ['n01728920', 'ringneck_snake'], + '54': ['n01729322', 'hognose_snake'], + '55': ['n01729977', 'green_snake'], + '56': ['n01734418', 'king_snake'], + '57': ['n01735189', 'garter_snake'], + '58': ['n01737021', 'water_snake'], + '59': ['n01739381', 'vine_snake'], + '60': ['n01740131', 'night_snake'], + '61': ['n01742172', 'boa_constrictor'], + '62': ['n01744401', 'rock_python'], + '63': ['n01748264', 'Indian_cobra'], + '64': ['n01749939', 'green_mamba'], + '65': ['n01751748', 'sea_snake'], + '66': ['n01753488', 'horned_viper'], + '67': ['n01755581', 'diamondback'], + '68': ['n01756291', 'sidewinder'], + '69': ['n01768244', 'trilobite'], + '70': ['n01770081', 'harvestman'], + '71': ['n01770393', 'scorpion'], + '72': ['n01773157', 'black_and_gold_garden_spider'], + '73': ['n01773549', 'barn_spider'], + '74': ['n01773797', 'garden_spider'], + '75': ['n01774384', 'black_widow'], + '76': ['n01774750', 'tarantula'], + '77': ['n01775062', 'wolf_spider'], + '78': ['n01776313', 'tick'], + '79': ['n01784675', 'centipede'], + '80': ['n01795545', 'black_grouse'], + '81': ['n01796340', 'ptarmigan'], + '82': ['n01797886', 'ruffed_grouse'], + '83': ['n01798484', 'prairie_chicken'], + '84': ['n01806143', 'peacock'], + '85': ['n01806567', 'quail'], + '86': ['n01807496', 'partridge'], + '87': ['n01817953', 'African_grey'], + '88': ['n01818515', 'macaw'], + '89': ['n01819313', 'sulphur-crested_cockatoo'], + '90': ['n01820546', 'lorikeet'], + '91': ['n01824575', 'coucal'], + '92': ['n01828970', 'bee_eater'], + '93': ['n01829413', 'hornbill'], + '94': ['n01833805', 'hummingbird'], + '95': ['n01843065', 'jacamar'], + '96': ['n01843383', 'toucan'], + '97': ['n01847000', 'drake'], + '98': ['n01855032', 'red-breasted_merganser'], + '99': ['n01855672', 'goose'], + '100': ['n01860187', 'black_swan'], + '101': ['n01871265', 'tusker'], + '102': ['n01872401', 'echidna'], + '103': ['n01873310', 'platypus'], + '104': ['n01877812', 'wallaby'], + '105': ['n01882714', 'koala'], + '106': ['n01883070', 'wombat'], + '107': ['n01910747', 'jellyfish'], + '108': ['n01914609', 'sea_anemone'], + '109': ['n01917289', 'brain_coral'], + '110': ['n01924916', 'flatworm'], + '111': ['n01930112', 'nematode'], + '112': ['n01943899', 'conch'], + '113': ['n01944390', 'snail'], + '114': ['n01945685', 'slug'], + '115': ['n01950731', 'sea_slug'], + '116': ['n01955084', 'chiton'], + '117': ['n01968897', 'chambered_nautilus'], + '118': ['n01978287', 'Dungeness_crab'], + '119': ['n01978455', 'rock_crab'], + '120': ['n01980166', 'fiddler_crab'], + '121': ['n01981276', 'king_crab'], + '122': ['n01983481', 'American_lobster'], + '123': ['n01984695', 'spiny_lobster'], + '124': ['n01985128', 'crayfish'], + '125': ['n01986214', 'hermit_crab'], + '126': ['n01990800', 'isopod'], + '127': ['n02002556', 'white_stork'], + '128': ['n02002724', 'black_stork'], + '129': ['n02006656', 'spoonbill'], + '130': ['n02007558', 'flamingo'], + '131': ['n02009229', 'little_blue_heron'], + '132': ['n02009912', 'American_egret'], + '133': ['n02011460', 'bittern'], + '134': ['n02012849', 'crane'], + '135': ['n02013706', 'limpkin'], + '136': ['n02017213', 'European_gallinule'], + '137': ['n02018207', 'American_coot'], + '138': ['n02018795', 'bustard'], + '139': ['n02025239', 'ruddy_turnstone'], + '140': ['n02027492', 'red-backed_sandpiper'], + '141': ['n02028035', 'redshank'], + '142': ['n02033041', 'dowitcher'], + '143': ['n02037110', 'oystercatcher'], + '144': ['n02051845', 'pelican'], + '145': ['n02056570', 'king_penguin'], + '146': ['n02058221', 'albatross'], + '147': ['n02066245', 'grey_whale'], + '148': ['n02071294', 'killer_whale'], + '149': ['n02074367', 'dugong'], + '150': ['n02077923', 'sea_lion'], + '151': ['n02085620', 'Chihuahua'], + '152': ['n02085782', 'Japanese_spaniel'], + '153': ['n02085936', 'Maltese_dog'], + '154': ['n02086079', 'Pekinese'], + '155': ['n02086240', 'Shih-Tzu'], + '156': ['n02086646', 'Blenheim_spaniel'], + '157': ['n02086910', 'papillon'], + '158': ['n02087046', 'toy_terrier'], + '159': ['n02087394', 'Rhodesian_ridgeback'], + '160': ['n02088094', 'Afghan_hound'], + '161': ['n02088238', 'basset'], + '162': ['n02088364', 'beagle'], + '163': ['n02088466', 'bloodhound'], + '164': ['n02088632', 'bluetick'], + '165': ['n02089078', 'black-and-tan_coonhound'], + '166': ['n02089867', 'Walker_hound'], + '167': ['n02089973', 'English_foxhound'], + '168': ['n02090379', 'redbone'], + '169': ['n02090622', 'borzoi'], + '170': ['n02090721', 'Irish_wolfhound'], + '171': ['n02091032', 'Italian_greyhound'], + '172': ['n02091134', 'whippet'], + '173': ['n02091244', 'Ibizan_hound'], + '174': ['n02091467', 'Norwegian_elkhound'], + '175': ['n02091635', 'otterhound'], + '176': ['n02091831', 'Saluki'], + '177': ['n02092002', 'Scottish_deerhound'], + '178': ['n02092339', 'Weimaraner'], + '179': ['n02093256', 'Staffordshire_bullterrier'], + '180': ['n02093428', 'American_Staffordshire_terrier'], + '181': ['n02093647', 'Bedlington_terrier'], + '182': ['n02093754', 'Border_terrier'], + '183': ['n02093859', 'Kerry_blue_terrier'], + '184': ['n02093991', 'Irish_terrier'], + '185': ['n02094114', 'Norfolk_terrier'], + '186': ['n02094258', 'Norwich_terrier'], + '187': ['n02094433', 'Yorkshire_terrier'], + '188': ['n02095314', 'wire-haired_fox_terrier'], + '189': ['n02095570', 'Lakeland_terrier'], + '190': ['n02095889', 'Sealyham_terrier'], + '191': ['n02096051', 'Airedale'], + '192': ['n02096177', 'cairn'], + '193': ['n02096294', 'Australian_terrier'], + '194': ['n02096437', 'Dandie_Dinmont'], + '195': ['n02096585', 'Boston_bull'], + '196': ['n02097047', 'miniature_schnauzer'], + '197': ['n02097130', 'giant_schnauzer'], + '198': ['n02097209', 'standard_schnauzer'], + '199': ['n02097298', 'Scotch_terrier'], + '200': ['n02097474', 'Tibetan_terrier'], + '201': ['n02097658', 'silky_terrier'], + '202': ['n02098105', 'soft-coated_wheaten_terrier'], + '203': ['n02098286', 'West_Highland_white_terrier'], + '204': ['n02098413', 'Lhasa'], + '205': ['n02099267', 'flat-coated_retriever'], + '206': ['n02099429', 'curly-coated_retriever'], + '207': ['n02099601', 'golden_retriever'], + '208': ['n02099712', 'Labrador_retriever'], + '209': ['n02099849', 'Chesapeake_Bay_retriever'], + '210': ['n02100236', 'German_short-haired_pointer'], + '211': ['n02100583', 'vizsla'], + '212': ['n02100735', 'English_setter'], + '213': ['n02100877', 'Irish_setter'], + '214': ['n02101006', 'Gordon_setter'], + '215': ['n02101388', 'Brittany_spaniel'], + '216': ['n02101556', 'clumber'], + '217': ['n02102040', 'English_springer'], + '218': ['n02102177', 'Welsh_springer_spaniel'], + '219': ['n02102318', 'cocker_spaniel'], + '220': ['n02102480', 'Sussex_spaniel'], + '221': ['n02102973', 'Irish_water_spaniel'], + '222': ['n02104029', 'kuvasz'], + '223': ['n02104365', 'schipperke'], + '224': ['n02105056', 'groenendael'], + '225': ['n02105162', 'malinois'], + '226': ['n02105251', 'briard'], + '227': ['n02105412', 'kelpie'], + '228': ['n02105505', 'komondor'], + '229': ['n02105641', 'Old_English_sheepdog'], + '230': ['n02105855', 'Shetland_sheepdog'], + '231': ['n02106030', 'collie'], + '232': ['n02106166', 'Border_collie'], + '233': ['n02106382', 'Bouvier_des_Flandres'], + '234': ['n02106550', 'Rottweiler'], + '235': ['n02106662', 'German_shepherd'], + '236': ['n02107142', 'Doberman'], + '237': ['n02107312', 'miniature_pinscher'], + '238': ['n02107574', 'Greater_Swiss_Mountain_dog'], + '239': ['n02107683', 'Bernese_mountain_dog'], + '240': ['n02107908', 'Appenzeller'], + '241': ['n02108000', 'EntleBucher'], + '242': ['n02108089', 'boxer'], + '243': ['n02108422', 'bull_mastiff'], + '244': ['n02108551', 'Tibetan_mastiff'], + '245': ['n02108915', 'French_bulldog'], + '246': ['n02109047', 'Great_Dane'], + '247': ['n02109525', 'Saint_Bernard'], + '248': ['n02109961', 'Eskimo_dog'], + '249': ['n02110063', 'malamute'], + '250': ['n02110185', 'Siberian_husky'], + '251': ['n02110341', 'dalmatian'], + '252': ['n02110627', 'affenpinscher'], + '253': ['n02110806', 'basenji'], + '254': ['n02110958', 'pug'], + '255': ['n02111129', 'Leonberg'], + '256': ['n02111277', 'Newfoundland'], + '257': ['n02111500', 'Great_Pyrenees'], + '258': ['n02111889', 'Samoyed'], + '259': ['n02112018', 'Pomeranian'], + '260': ['n02112137', 'chow'], + '261': ['n02112350', 'keeshond'], + '262': ['n02112706', 'Brabancon_griffon'], + '263': ['n02113023', 'Pembroke'], + '264': ['n02113186', 'Cardigan'], + '265': ['n02113624', 'toy_poodle'], + '266': ['n02113712', 'miniature_poodle'], + '267': ['n02113799', 'standard_poodle'], + '268': ['n02113978', 'Mexican_hairless'], + '269': ['n02114367', 'timber_wolf'], + '270': ['n02114548', 'white_wolf'], + '271': ['n02114712', 'red_wolf'], + '272': ['n02114855', 'coyote'], + '273': ['n02115641', 'dingo'], + '274': ['n02115913', 'dhole'], + '275': ['n02116738', 'African_hunting_dog'], + '276': ['n02117135', 'hyena'], + '277': ['n02119022', 'red_fox'], + '278': ['n02119789', 'kit_fox'], + '279': ['n02120079', 'Arctic_fox'], + '280': ['n02120505', 'grey_fox'], + '281': ['n02123045', 'tabby'], + '282': ['n02123159', 'tiger_cat'], + '283': ['n02123394', 'Persian_cat'], + '284': ['n02123597', 'Siamese_cat'], + '285': ['n02124075', 'Egyptian_cat'], + '286': ['n02125311', 'cougar'], + '287': ['n02127052', 'lynx'], + '288': ['n02128385', 'leopard'], + '289': ['n02128757', 'snow_leopard'], + '290': ['n02128925', 'jaguar'], + '291': ['n02129165', 'lion'], + '292': ['n02129604', 'tiger'], + '293': ['n02130308', 'cheetah'], + '294': ['n02132136', 'brown_bear'], + '295': ['n02133161', 'American_black_bear'], + '296': ['n02134084', 'ice_bear'], + '297': ['n02134418', 'sloth_bear'], + '298': ['n02137549', 'mongoose'], + '299': ['n02138441', 'meerkat'], + '300': ['n02165105', 'tiger_beetle'], + '301': ['n02165456', 'ladybug'], + '302': ['n02167151', 'ground_beetle'], + '303': ['n02168699', 'long-horned_beetle'], + '304': ['n02169497', 'leaf_beetle'], + '305': ['n02172182', 'dung_beetle'], + '306': ['n02174001', 'rhinoceros_beetle'], + '307': ['n02177972', 'weevil'], + '308': ['n02190166', 'fly'], + '309': ['n02206856', 'bee'], + '310': ['n02219486', 'ant'], + '311': ['n02226429', 'grasshopper'], + '312': ['n02229544', 'cricket'], + '313': ['n02231487', 'walking_stick'], + '314': ['n02233338', 'cockroach'], + '315': ['n02236044', 'mantis'], + '316': ['n02256656', 'cicada'], + '317': ['n02259212', 'leafhopper'], + '318': ['n02264363', 'lacewing'], + '319': ['n02268443', 'dragonfly'], + '320': ['n02268853', 'damselfly'], + '321': ['n02276258', 'admiral'], + '322': ['n02277742', 'ringlet'], + '323': ['n02279972', 'monarch'], + '324': ['n02280649', 'cabbage_butterfly'], + '325': ['n02281406', 'sulphur_butterfly'], + '326': ['n02281787', 'lycaenid'], + '327': ['n02317335', 'starfish'], + '328': ['n02319095', 'sea_urchin'], + '329': ['n02321529', 'sea_cucumber'], + '330': ['n02325366', 'wood_rabbit'], + '331': ['n02326432', 'hare'], + '332': ['n02328150', 'Angora'], + '333': ['n02342885', 'hamster'], + '334': ['n02346627', 'porcupine'], + '335': ['n02356798', 'fox_squirrel'], + '336': ['n02361337', 'marmot'], + '337': ['n02363005', 'beaver'], + '338': ['n02364673', 'guinea_pig'], + '339': ['n02389026', 'sorrel'], + '340': ['n02391049', 'zebra'], + '341': ['n02395406', 'hog'], + '342': ['n02396427', 'wild_boar'], + '343': ['n02397096', 'warthog'], + '344': ['n02398521', 'hippopotamus'], + '345': ['n02403003', 'ox'], + '346': ['n02408429', 'water_buffalo'], + '347': ['n02410509', 'bison'], + '348': ['n02412080', 'ram'], + '349': ['n02415577', 'bighorn'], + '350': ['n02417914', 'ibex'], + '351': ['n02422106', 'hartebeest'], + '352': ['n02422699', 'impala'], + '353': ['n02423022', 'gazelle'], + '354': ['n02437312', 'Arabian_camel'], + '355': ['n02437616', 'llama'], + '356': ['n02441942', 'weasel'], + '357': ['n02442845', 'mink'], + '358': ['n02443114', 'polecat'], + '359': ['n02443484', 'black-footed_ferret'], + '360': ['n02444819', 'otter'], + '361': ['n02445715', 'skunk'], + '362': ['n02447366', 'badger'], + '363': ['n02454379', 'armadillo'], + '364': ['n02457408', 'three-toed_sloth'], + '365': ['n02480495', 'orangutan'], + '366': ['n02480855', 'gorilla'], + '367': ['n02481823', 'chimpanzee'], + '368': ['n02483362', 'gibbon'], + '369': ['n02483708', 'siamang'], + '370': ['n02484975', 'guenon'], + '371': ['n02486261', 'patas'], + '372': ['n02486410', 'baboon'], + '373': ['n02487347', 'macaque'], + '374': ['n02488291', 'langur'], + '375': ['n02488702', 'colobus'], + '376': ['n02489166', 'proboscis_monkey'], + '377': ['n02490219', 'marmoset'], + '378': ['n02492035', 'capuchin'], + '379': ['n02492660', 'howler_monkey'], + '380': ['n02493509', 'titi'], + '381': ['n02493793', 'spider_monkey'], + '382': ['n02494079', 'squirrel_monkey'], + '383': ['n02497673', 'Madagascar_cat'], + '384': ['n02500267', 'indri'], + '385': ['n02504013', 'Indian_elephant'], + '386': ['n02504458', 'African_elephant'], + '387': ['n02509815', 'lesser_panda'], + '388': ['n02510455', 'giant_panda'], + '389': ['n02514041', 'barracouta'], + '390': ['n02526121', 'eel'], + '391': ['n02536864', 'coho'], + '392': ['n02606052', 'rock_beauty'], + '393': ['n02607072', 'anemone_fish'], + '394': ['n02640242', 'sturgeon'], + '395': ['n02641379', 'gar'], + '396': ['n02643566', 'lionfish'], + '397': ['n02655020', 'puffer'], + '398': ['n02666196', 'abacus'], + '399': ['n02667093', 'abaya'], + '400': ['n02669723', 'academic_gown'], + '401': ['n02672831', 'accordion'], + '402': ['n02676566', 'acoustic_guitar'], + '403': ['n02687172', 'aircraft_carrier'], + '404': ['n02690373', 'airliner'], + '405': ['n02692877', 'airship'], + '406': ['n02699494', 'altar'], + '407': ['n02701002', 'ambulance'], + '408': ['n02704792', 'amphibian'], + '409': ['n02708093', 'analog_clock'], + '410': ['n02727426', 'apiary'], + '411': ['n02730930', 'apron'], + '412': ['n02747177', 'ashcan'], + '413': ['n02749479', 'assault_rifle'], + '414': ['n02769748', 'backpack'], + '415': ['n02776631', 'bakery'], + '416': ['n02777292', 'balance_beam'], + '417': ['n02782093', 'balloon'], + '418': ['n02783161', 'ballpoint'], + '419': ['n02786058', 'Band_Aid'], + '420': ['n02787622', 'banjo'], + '421': ['n02788148', 'bannister'], + '422': ['n02790996', 'barbell'], + '423': ['n02791124', 'barber_chair'], + '424': ['n02791270', 'barbershop'], + '425': ['n02793495', 'barn'], + '426': ['n02794156', 'barometer'], + '427': ['n02795169', 'barrel'], + '428': ['n02797295', 'barrow'], + '429': ['n02799071', 'baseball'], + '430': ['n02802426', 'basketball'], + '431': ['n02804414', 'bassinet'], + '432': ['n02804610', 'bassoon'], + '433': ['n02807133', 'bathing_cap'], + '434': ['n02808304', 'bath_towel'], + '435': ['n02808440', 'bathtub'], + '436': ['n02814533', 'beach_wagon'], + '437': ['n02814860', 'beacon'], + '438': ['n02815834', 'beaker'], + '439': ['n02817516', 'bearskin'], + '440': ['n02823428', 'beer_bottle'], + '441': ['n02823750', 'beer_glass'], + '442': ['n02825657', 'bell_cote'], + '443': ['n02834397', 'bib'], + '444': ['n02835271', 'bicycle-built-for-two'], + '445': ['n02837789', 'bikini'], + '446': ['n02840245', 'binder'], + '447': ['n02841315', 'binoculars'], + '448': ['n02843684', 'birdhouse'], + '449': ['n02859443', 'boathouse'], + '450': ['n02860847', 'bobsled'], + '451': ['n02865351', 'bolo_tie'], + '452': ['n02869837', 'bonnet'], + '453': ['n02870880', 'bookcase'], + '454': ['n02871525', 'bookshop'], + '455': ['n02877765', 'bottlecap'], + '456': ['n02879718', 'bow'], + '457': ['n02883205', 'bow_tie'], + '458': ['n02892201', 'brass'], + '459': ['n02892767', 'brassiere'], + '460': ['n02894605', 'breakwater'], + '461': ['n02895154', 'breastplate'], + '462': ['n02906734', 'broom'], + '463': ['n02909870', 'bucket'], + '464': ['n02910353', 'buckle'], + '465': ['n02916936', 'bulletproof_vest'], + '466': ['n02917067', 'bullet_train'], + '467': ['n02927161', 'butcher_shop'], + '468': ['n02930766', 'cab'], + '469': ['n02939185', 'caldron'], + '470': ['n02948072', 'candle'], + '471': ['n02950826', 'cannon'], + '472': ['n02951358', 'canoe'], + '473': ['n02951585', 'can_opener'], + '474': ['n02963159', 'cardigan'], + '475': ['n02965783', 'car_mirror'], + '476': ['n02966193', 'carousel'], + '477': ['n02966687', "carpenter's_kit"], + '478': ['n02971356', 'carton'], + '479': ['n02974003', 'car_wheel'], + '480': ['n02977058', 'cash_machine'], + '481': ['n02978881', 'cassette'], + '482': ['n02979186', 'cassette_player'], + '483': ['n02980441', 'castle'], + '484': ['n02981792', 'catamaran'], + '485': ['n02988304', 'CD_player'], + '486': ['n02992211', 'cello'], + '487': ['n02992529', 'cellular_telephone'], + '488': ['n02999410', 'chain'], + '489': ['n03000134', 'chainlink_fence'], + '490': ['n03000247', 'chain_mail'], + '491': ['n03000684', 'chain_saw'], + '492': ['n03014705', 'chest'], + '493': ['n03016953', 'chiffonier'], + '494': ['n03017168', 'chime'], + '495': ['n03018349', 'china_cabinet'], + '496': ['n03026506', 'Christmas_stocking'], + '497': ['n03028079', 'church'], + '498': ['n03032252', 'cinema'], + '499': ['n03041632', 'cleaver'], + '500': ['n03042490', 'cliff_dwelling'], + '501': ['n03045698', 'cloak'], + '502': ['n03047690', 'clog'], + '503': ['n03062245', 'cocktail_shaker'], + '504': ['n03063599', 'coffee_mug'], + '505': ['n03063689', 'coffeepot'], + '506': ['n03065424', 'coil'], + '507': ['n03075370', 'combination_lock'], + '508': ['n03085013', 'computer_keyboard'], + '509': ['n03089624', 'confectionery'], + '510': ['n03095699', 'container_ship'], + '511': ['n03100240', 'convertible'], + '512': ['n03109150', 'corkscrew'], + '513': ['n03110669', 'cornet'], + '514': ['n03124043', 'cowboy_boot'], + '515': ['n03124170', 'cowboy_hat'], + '516': ['n03125729', 'cradle'], + '517': ['n03126707', 'crane'], + '518': ['n03127747', 'crash_helmet'], + '519': ['n03127925', 'crate'], + '520': ['n03131574', 'crib'], + '521': ['n03133878', 'Crock_Pot'], + '522': ['n03134739', 'croquet_ball'], + '523': ['n03141823', 'crutch'], + '524': ['n03146219', 'cuirass'], + '525': ['n03160309', 'dam'], + '526': ['n03179701', 'desk'], + '527': ['n03180011', 'desktop_computer'], + '528': ['n03187595', 'dial_telephone'], + '529': ['n03188531', 'diaper'], + '530': ['n03196217', 'digital_clock'], + '531': ['n03197337', 'digital_watch'], + '532': ['n03201208', 'dining_table'], + '533': ['n03207743', 'dishrag'], + '534': ['n03207941', 'dishwasher'], + '535': ['n03208938', 'disk_brake'], + '536': ['n03216828', 'dock'], + '537': ['n03218198', 'dogsled'], + '538': ['n03220513', 'dome'], + '539': ['n03223299', 'doormat'], + '540': ['n03240683', 'drilling_platform'], + '541': ['n03249569', 'drum'], + '542': ['n03250847', 'drumstick'], + '543': ['n03255030', 'dumbbell'], + '544': ['n03259280', 'Dutch_oven'], + '545': ['n03271574', 'electric_fan'], + '546': ['n03272010', 'electric_guitar'], + '547': ['n03272562', 'electric_locomotive'], + '548': ['n03290653', 'entertainment_center'], + '549': ['n03291819', 'envelope'], + '550': ['n03297495', 'espresso_maker'], + '551': ['n03314780', 'face_powder'], + '552': ['n03325584', 'feather_boa'], + '553': ['n03337140', 'file'], + '554': ['n03344393', 'fireboat'], + '555': ['n03345487', 'fire_engine'], + '556': ['n03347037', 'fire_screen'], + '557': ['n03355925', 'flagpole'], + '558': ['n03372029', 'flute'], + '559': ['n03376595', 'folding_chair'], + '560': ['n03379051', 'football_helmet'], + '561': ['n03384352', 'forklift'], + '562': ['n03388043', 'fountain'], + '563': ['n03388183', 'fountain_pen'], + '564': ['n03388549', 'four-poster'], + '565': ['n03393912', 'freight_car'], + '566': ['n03394916', 'French_horn'], + '567': ['n03400231', 'frying_pan'], + '568': ['n03404251', 'fur_coat'], + '569': ['n03417042', 'garbage_truck'], + '570': ['n03424325', 'gasmask'], + '571': ['n03425413', 'gas_pump'], + '572': ['n03443371', 'goblet'], + '573': ['n03444034', 'go-kart'], + '574': ['n03445777', 'golf_ball'], + '575': ['n03445924', 'golfcart'], + '576': ['n03447447', 'gondola'], + '577': ['n03447721', 'gong'], + '578': ['n03450230', 'gown'], + '579': ['n03452741', 'grand_piano'], + '580': ['n03457902', 'greenhouse'], + '581': ['n03459775', 'grille'], + '582': ['n03461385', 'grocery_store'], + '583': ['n03467068', 'guillotine'], + '584': ['n03476684', 'hair_slide'], + '585': ['n03476991', 'hair_spray'], + '586': ['n03478589', 'half_track'], + '587': ['n03481172', 'hammer'], + '588': ['n03482405', 'hamper'], + '589': ['n03483316', 'hand_blower'], + '590': ['n03485407', 'hand-held_computer'], + '591': ['n03485794', 'handkerchief'], + '592': ['n03492542', 'hard_disc'], + '593': ['n03494278', 'harmonica'], + '594': ['n03495258', 'harp'], + '595': ['n03496892', 'harvester'], + '596': ['n03498962', 'hatchet'], + '597': ['n03527444', 'holster'], + '598': ['n03529860', 'home_theater'], + '599': ['n03530642', 'honeycomb'], + '600': ['n03532672', 'hook'], + '601': ['n03534580', 'hoopskirt'], + '602': ['n03535780', 'horizontal_bar'], + '603': ['n03538406', 'horse_cart'], + '604': ['n03544143', 'hourglass'], + '605': ['n03584254', 'iPod'], + '606': ['n03584829', 'iron'], + '607': ['n03590841', "jack-o'-lantern"], + '608': ['n03594734', 'jean'], + '609': ['n03594945', 'jeep'], + '610': ['n03595614', 'jersey'], + '611': ['n03598930', 'jigsaw_puzzle'], + '612': ['n03599486', 'jinrikisha'], + '613': ['n03602883', 'joystick'], + '614': ['n03617480', 'kimono'], + '615': ['n03623198', 'knee_pad'], + '616': ['n03627232', 'knot'], + '617': ['n03630383', 'lab_coat'], + '618': ['n03633091', 'ladle'], + '619': ['n03637318', 'lampshade'], + '620': ['n03642806', 'laptop'], + '621': ['n03649909', 'lawn_mower'], + '622': ['n03657121', 'lens_cap'], + '623': ['n03658185', 'letter_opener'], + '624': ['n03661043', 'library'], + '625': ['n03662601', 'lifeboat'], + '626': ['n03666591', 'lighter'], + '627': ['n03670208', 'limousine'], + '628': ['n03673027', 'liner'], + '629': ['n03676483', 'lipstick'], + '630': ['n03680355', 'Loafer'], + '631': ['n03690938', 'lotion'], + '632': ['n03691459', 'loudspeaker'], + '633': ['n03692522', 'loupe'], + '634': ['n03697007', 'lumbermill'], + '635': ['n03706229', 'magnetic_compass'], + '636': ['n03709823', 'mailbag'], + '637': ['n03710193', 'mailbox'], + '638': ['n03710637', 'maillot'], + '639': ['n03710721', 'maillot'], + '640': ['n03717622', 'manhole_cover'], + '641': ['n03720891', 'maraca'], + '642': ['n03721384', 'marimba'], + '643': ['n03724870', 'mask'], + '644': ['n03729826', 'matchstick'], + '645': ['n03733131', 'maypole'], + '646': ['n03733281', 'maze'], + '647': ['n03733805', 'measuring_cup'], + '648': ['n03742115', 'medicine_chest'], + '649': ['n03743016', 'megalith'], + '650': ['n03759954', 'microphone'], + '651': ['n03761084', 'microwave'], + '652': ['n03763968', 'military_uniform'], + '653': ['n03764736', 'milk_can'], + '654': ['n03769881', 'minibus'], + '655': ['n03770439', 'miniskirt'], + '656': ['n03770679', 'minivan'], + '657': ['n03773504', 'missile'], + '658': ['n03775071', 'mitten'], + '659': ['n03775546', 'mixing_bowl'], + '660': ['n03776460', 'mobile_home'], + '661': ['n03777568', 'Model_T'], + '662': ['n03777754', 'modem'], + '663': ['n03781244', 'monastery'], + '664': ['n03782006', 'monitor'], + '665': ['n03785016', 'moped'], + '666': ['n03786901', 'mortar'], + '667': ['n03787032', 'mortarboard'], + '668': ['n03788195', 'mosque'], + '669': ['n03788365', 'mosquito_net'], + '670': ['n03791053', 'motor_scooter'], + '671': ['n03792782', 'mountain_bike'], + '672': ['n03792972', 'mountain_tent'], + '673': ['n03793489', 'mouse'], + '674': ['n03794056', 'mousetrap'], + '675': ['n03796401', 'moving_van'], + '676': ['n03803284', 'muzzle'], + '677': ['n03804744', 'nail'], + '678': ['n03814639', 'neck_brace'], + '679': ['n03814906', 'necklace'], + '680': ['n03825788', 'nipple'], + '681': ['n03832673', 'notebook'], + '682': ['n03837869', 'obelisk'], + '683': ['n03838899', 'oboe'], + '684': ['n03840681', 'ocarina'], + '685': ['n03841143', 'odometer'], + '686': ['n03843555', 'oil_filter'], + '687': ['n03854065', 'organ'], + '688': ['n03857828', 'oscilloscope'], + '689': ['n03866082', 'overskirt'], + '690': ['n03868242', 'oxcart'], + '691': ['n03868863', 'oxygen_mask'], + '692': ['n03871628', 'packet'], + '693': ['n03873416', 'paddle'], + '694': ['n03874293', 'paddlewheel'], + '695': ['n03874599', 'padlock'], + '696': ['n03876231', 'paintbrush'], + '697': ['n03877472', 'pajama'], + '698': ['n03877845', 'palace'], + '699': ['n03884397', 'panpipe'], + '700': ['n03887697', 'paper_towel'], + '701': ['n03888257', 'parachute'], + '702': ['n03888605', 'parallel_bars'], + '703': ['n03891251', 'park_bench'], + '704': ['n03891332', 'parking_meter'], + '705': ['n03895866', 'passenger_car'], + '706': ['n03899768', 'patio'], + '707': ['n03902125', 'pay-phone'], + '708': ['n03903868', 'pedestal'], + '709': ['n03908618', 'pencil_box'], + '710': ['n03908714', 'pencil_sharpener'], + '711': ['n03916031', 'perfume'], + '712': ['n03920288', 'Petri_dish'], + '713': ['n03924679', 'photocopier'], + '714': ['n03929660', 'pick'], + '715': ['n03929855', 'pickelhaube'], + '716': ['n03930313', 'picket_fence'], + '717': ['n03930630', 'pickup'], + '718': ['n03933933', 'pier'], + '719': ['n03935335', 'piggy_bank'], + '720': ['n03937543', 'pill_bottle'], + '721': ['n03938244', 'pillow'], + '722': ['n03942813', 'ping-pong_ball'], + '723': ['n03944341', 'pinwheel'], + '724': ['n03947888', 'pirate'], + '725': ['n03950228', 'pitcher'], + '726': ['n03954731', 'plane'], + '727': ['n03956157', 'planetarium'], + '728': ['n03958227', 'plastic_bag'], + '729': ['n03961711', 'plate_rack'], + '730': ['n03967562', 'plow'], + '731': ['n03970156', 'plunger'], + '732': ['n03976467', 'Polaroid_camera'], + '733': ['n03976657', 'pole'], + '734': ['n03977966', 'police_van'], + '735': ['n03980874', 'poncho'], + '736': ['n03982430', 'pool_table'], + '737': ['n03983396', 'pop_bottle'], + '738': ['n03991062', 'pot'], + '739': ['n03992509', "potter's_wheel"], + '740': ['n03995372', 'power_drill'], + '741': ['n03998194', 'prayer_rug'], + '742': ['n04004767', 'printer'], + '743': ['n04005630', 'prison'], + '744': ['n04008634', 'projectile'], + '745': ['n04009552', 'projector'], + '746': ['n04019541', 'puck'], + '747': ['n04023962', 'punching_bag'], + '748': ['n04026417', 'purse'], + '749': ['n04033901', 'quill'], + '750': ['n04033995', 'quilt'], + '751': ['n04037443', 'racer'], + '752': ['n04039381', 'racket'], + '753': ['n04040759', 'radiator'], + '754': ['n04041544', 'radio'], + '755': ['n04044716', 'radio_telescope'], + '756': ['n04049303', 'rain_barrel'], + '757': ['n04065272', 'recreational_vehicle'], + '758': ['n04067472', 'reel'], + '759': ['n04069434', 'reflex_camera'], + '760': ['n04070727', 'refrigerator'], + '761': ['n04074963', 'remote_control'], + '762': ['n04081281', 'restaurant'], + '763': ['n04086273', 'revolver'], + '764': ['n04090263', 'rifle'], + '765': ['n04099969', 'rocking_chair'], + '766': ['n04111531', 'rotisserie'], + '767': ['n04116512', 'rubber_eraser'], + '768': ['n04118538', 'rugby_ball'], + '769': ['n04118776', 'rule'], + '770': ['n04120489', 'running_shoe'], + '771': ['n04125021', 'safe'], + '772': ['n04127249', 'safety_pin'], + '773': ['n04131690', 'saltshaker'], + '774': ['n04133789', 'sandal'], + '775': ['n04136333', 'sarong'], + '776': ['n04141076', 'sax'], + '777': ['n04141327', 'scabbard'], + '778': ['n04141975', 'scale'], + '779': ['n04146614', 'school_bus'], + '780': ['n04147183', 'schooner'], + '781': ['n04149813', 'scoreboard'], + '782': ['n04152593', 'screen'], + '783': ['n04153751', 'screw'], + '784': ['n04154565', 'screwdriver'], + '785': ['n04162706', 'seat_belt'], + '786': ['n04179913', 'sewing_machine'], + '787': ['n04192698', 'shield'], + '788': ['n04200800', 'shoe_shop'], + '789': ['n04201297', 'shoji'], + '790': ['n04204238', 'shopping_basket'], + '791': ['n04204347', 'shopping_cart'], + '792': ['n04208210', 'shovel'], + '793': ['n04209133', 'shower_cap'], + '794': ['n04209239', 'shower_curtain'], + '795': ['n04228054', 'ski'], + '796': ['n04229816', 'ski_mask'], + '797': ['n04235860', 'sleeping_bag'], + '798': ['n04238763', 'slide_rule'], + '799': ['n04239074', 'sliding_door'], + '800': ['n04243546', 'slot'], + '801': ['n04251144', 'snorkel'], + '802': ['n04252077', 'snowmobile'], + '803': ['n04252225', 'snowplow'], + '804': ['n04254120', 'soap_dispenser'], + '805': ['n04254680', 'soccer_ball'], + '806': ['n04254777', 'sock'], + '807': ['n04258138', 'solar_dish'], + '808': ['n04259630', 'sombrero'], + '809': ['n04263257', 'soup_bowl'], + '810': ['n04264628', 'space_bar'], + '811': ['n04265275', 'space_heater'], + '812': ['n04266014', 'space_shuttle'], + '813': ['n04270147', 'spatula'], + '814': ['n04273569', 'speedboat'], + '815': ['n04275548', 'spider_web'], + '816': ['n04277352', 'spindle'], + '817': ['n04285008', 'sports_car'], + '818': ['n04286575', 'spotlight'], + '819': ['n04296562', 'stage'], + '820': ['n04310018', 'steam_locomotive'], + '821': ['n04311004', 'steel_arch_bridge'], + '822': ['n04311174', 'steel_drum'], + '823': ['n04317175', 'stethoscope'], + '824': ['n04325704', 'stole'], + '825': ['n04326547', 'stone_wall'], + '826': ['n04328186', 'stopwatch'], + '827': ['n04330267', 'stove'], + '828': ['n04332243', 'strainer'], + '829': ['n04335435', 'streetcar'], + '830': ['n04336792', 'stretcher'], + '831': ['n04344873', 'studio_couch'], + '832': ['n04346328', 'stupa'], + '833': ['n04347754', 'submarine'], + '834': ['n04350905', 'suit'], + '835': ['n04355338', 'sundial'], + '836': ['n04355933', 'sunglass'], + '837': ['n04356056', 'sunglasses'], + '838': ['n04357314', 'sunscreen'], + '839': ['n04366367', 'suspension_bridge'], + '840': ['n04367480', 'swab'], + '841': ['n04370456', 'sweatshirt'], + '842': ['n04371430', 'swimming_trunks'], + '843': ['n04371774', 'swing'], + '844': ['n04372370', 'switch'], + '845': ['n04376876', 'syringe'], + '846': ['n04380533', 'table_lamp'], + '847': ['n04389033', 'tank'], + '848': ['n04392985', 'tape_player'], + '849': ['n04398044', 'teapot'], + '850': ['n04399382', 'teddy'], + '851': ['n04404412', 'television'], + '852': ['n04409515', 'tennis_ball'], + '853': ['n04417672', 'thatch'], + '854': ['n04418357', 'theater_curtain'], + '855': ['n04423845', 'thimble'], + '856': ['n04428191', 'thresher'], + '857': ['n04429376', 'throne'], + '858': ['n04435653', 'tile_roof'], + '859': ['n04442312', 'toaster'], + '860': ['n04443257', 'tobacco_shop'], + '861': ['n04447861', 'toilet_seat'], + '862': ['n04456115', 'torch'], + '863': ['n04458633', 'totem_pole'], + '864': ['n04461696', 'tow_truck'], + '865': ['n04462240', 'toyshop'], + '866': ['n04465501', 'tractor'], + '867': ['n04467665', 'trailer_truck'], + '868': ['n04476259', 'tray'], + '869': ['n04479046', 'trench_coat'], + '870': ['n04482393', 'tricycle'], + '871': ['n04483307', 'trimaran'], + '872': ['n04485082', 'tripod'], + '873': ['n04486054', 'triumphal_arch'], + '874': ['n04487081', 'trolleybus'], + '875': ['n04487394', 'trombone'], + '876': ['n04493381', 'tub'], + '877': ['n04501370', 'turnstile'], + '878': ['n04505470', 'typewriter_keyboard'], + '879': ['n04507155', 'umbrella'], + '880': ['n04509417', 'unicycle'], + '881': ['n04515003', 'upright'], + '882': ['n04517823', 'vacuum'], + '883': ['n04522168', 'vase'], + '884': ['n04523525', 'vault'], + '885': ['n04525038', 'velvet'], + '886': ['n04525305', 'vending_machine'], + '887': ['n04532106', 'vestment'], + '888': ['n04532670', 'viaduct'], + '889': ['n04536866', 'violin'], + '890': ['n04540053', 'volleyball'], + '891': ['n04542943', 'waffle_iron'], + '892': ['n04548280', 'wall_clock'], + '893': ['n04548362', 'wallet'], + '894': ['n04550184', 'wardrobe'], + '895': ['n04552348', 'warplane'], + '896': ['n04553703', 'washbasin'], + '897': ['n04554684', 'washer'], + '898': ['n04557648', 'water_bottle'], + '899': ['n04560804', 'water_jug'], + '900': ['n04562935', 'water_tower'], + '901': ['n04579145', 'whiskey_jug'], + '902': ['n04579432', 'whistle'], + '903': ['n04584207', 'wig'], + '904': ['n04589890', 'window_screen'], + '905': ['n04590129', 'window_shade'], + '906': ['n04591157', 'Windsor_tie'], + '907': ['n04591713', 'wine_bottle'], + '908': ['n04592741', 'wing'], + '909': ['n04596742', 'wok'], + '910': ['n04597913', 'wooden_spoon'], + '911': ['n04599235', 'wool'], + '912': ['n04604644', 'worm_fence'], + '913': ['n04606251', 'wreck'], + '914': ['n04612504', 'yawl'], + '915': ['n04613696', 'yurt'], + '916': ['n06359193', 'web_site'], + '917': ['n06596364', 'comic_book'], + '918': ['n06785654', 'crossword_puzzle'], + '919': ['n06794110', 'street_sign'], + '920': ['n06874185', 'traffic_light'], + '921': ['n07248320', 'book_jacket'], + '922': ['n07565083', 'menu'], + '923': ['n07579787', 'plate'], + '924': ['n07583066', 'guacamole'], + '925': ['n07584110', 'consomme'], + '926': ['n07590611', 'hot_pot'], + '927': ['n07613480', 'trifle'], + '928': ['n07614500', 'ice_cream'], + '929': ['n07615774', 'ice_lolly'], + '930': ['n07684084', 'French_loaf'], + '931': ['n07693725', 'bagel'], + '932': ['n07695742', 'pretzel'], + '933': ['n07697313', 'cheeseburger'], + '934': ['n07697537', 'hotdog'], + '935': ['n07711569', 'mashed_potato'], + '936': ['n07714571', 'head_cabbage'], + '937': ['n07714990', 'broccoli'], + '938': ['n07715103', 'cauliflower'], + '939': ['n07716358', 'zucchini'], + '940': ['n07716906', 'spaghetti_squash'], + '941': ['n07717410', 'acorn_squash'], + '942': ['n07717556', 'butternut_squash'], + '943': ['n07718472', 'cucumber'], + '944': ['n07718747', 'artichoke'], + '945': ['n07720875', 'bell_pepper'], + '946': ['n07730033', 'cardoon'], + '947': ['n07734744', 'mushroom'], + '948': ['n07742313', 'Granny_Smith'], + '949': ['n07745940', 'strawberry'], + '950': ['n07747607', 'orange'], + '951': ['n07749582', 'lemon'], + '952': ['n07753113', 'fig'], + '953': ['n07753275', 'pineapple'], + '954': ['n07753592', 'banana'], + '955': ['n07754684', 'jackfruit'], + '956': ['n07760859', 'custard_apple'], + '957': ['n07768694', 'pomegranate'], + '958': ['n07802026', 'hay'], + '959': ['n07831146', 'carbonara'], + '960': ['n07836838', 'chocolate_sauce'], + '961': ['n07860988', 'dough'], + '962': ['n07871810', 'meat_loaf'], + '963': ['n07873807', 'pizza'], + '964': ['n07875152', 'potpie'], + '965': ['n07880968', 'burrito'], + '966': ['n07892512', 'red_wine'], + '967': ['n07920052', 'espresso'], + '968': ['n07930864', 'cup'], + '969': ['n07932039', 'eggnog'], + '970': ['n09193705', 'alp'], + '971': ['n09229709', 'bubble'], + '972': ['n09246464', 'cliff'], + '973': ['n09256479', 'coral_reef'], + '974': ['n09288635', 'geyser'], + '975': ['n09332890', 'lakeside'], + '976': ['n09399592', 'promontory'], + '977': ['n09421951', 'sandbar'], + '978': ['n09428293', 'seashore'], + '979': ['n09468604', 'valley'], + '980': ['n09472597', 'volcano'], + '981': ['n09835506', 'ballplayer'], + '982': ['n10148035', 'groom'], + '983': ['n10565667', 'scuba_diver'], + '984': ['n11879895', 'rapeseed'], + '985': ['n11939491', 'daisy'], + '986': ['n12057211', "yellow_lady's_slipper"], + '987': ['n12144580', 'corn'], + '988': ['n12267677', 'acorn'], + '989': ['n12620546', 'hip'], + '990': ['n12768682', 'buckeye'], + '991': ['n12985857', 'coral_fungus'], + '992': ['n12998815', 'agaric'], + '993': ['n13037406', 'gyromitra'], + '994': ['n13040303', 'stinkhorn'], + '995': ['n13044778', 'earthstar'], + '996': ['n13052670', 'hen-of-the-woods'], + '997': ['n13054560', 'bolete'], + '998': ['n13133613', 'ear'], + '999': ['n15075141', 'toilet_tissue'] +} diff --git a/myproj/src/utils/index.js b/myproj/src/utils/index.js new file mode 100644 index 0000000000..df76327c2f --- /dev/null +++ b/myproj/src/utils/index.js @@ -0,0 +1,196 @@ +import unpack from 'ndarray-unpack' +import _ from 'lodash' +import { imagenetClasses } from './imagenet' + +/** + * Find mindpoint of two points + */ +export function getMidpoint(p1, p2) { + const [x1, y1] = p1 + const [x2, y2] = p2 + return [x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2] +} + +/** + * Gets the (x, y) coordinates of an UI event relative to its target, + * e.g., canvas. Accounts for touch events as well as mouse events. + */ +export function getCoordinates(e) { + let { clientX, clientY } = e + // for touch event + if (e.touches && e.touches.length) { + clientX = e.touches[0].clientX + clientY = e.touches[0].clientY + } + const { left, top } = e.target.getBoundingClientRect() + const [x, y] = [clientX - left, clientY - top] + return [x, y] +} + +/** + * Centers and crops canvas ImageData based on alpha channel. + * @param {ImageData} imageData + * @returns {ImageData} + */ +export function centerCrop(imageData) { + const { data, width, height } = imageData + let [xmin, ymin] = [width, height] + let [xmax, ymax] = [-1, -1] + for (let i = 0; i < width; i++) { + for (let j = 0; j < height; j++) { + const idx = i + j * width + if (data[4 * idx + 3] > 0) { + if (i < xmin) xmin = i + if (i > xmax) xmax = i + if (j < ymin) ymin = j + if (j > ymax) ymax = j + } + } + } + + // add a little padding + xmin -= 20 + xmax += 20 + ymin -= 20 + ymax += 20 + + // make bounding box square + let [widthNew, heightNew] = [xmax - xmin + 1, ymax - ymin + 1] + if (widthNew < heightNew) { + // new width < new height + const halfBefore = Math.floor((heightNew - widthNew) / 2) + const halfAfter = heightNew - widthNew - halfBefore + xmax += halfAfter + xmin -= halfBefore + } else if (widthNew > heightNew) { + // new width > new height + const halfBefore = Math.floor((widthNew - heightNew) / 2) + const halfAfter = widthNew - heightNew - halfBefore + ymax += halfAfter + ymin -= halfBefore + } + + widthNew = xmax - xmin + 1 + heightNew = ymax - ymin + 1 + let dataNew = new Uint8ClampedArray(widthNew * heightNew * 4) + for (let i = xmin; i <= xmax; i++) { + for (let j = ymin; j <= ymax; j++) { + if (i >= 0 && i < width && j >= 0 && j < height) { + const idx = i + j * width + const idxNew = i - xmin + (j - ymin) * widthNew + dataNew[4 * idxNew + 3] = data[4 * idx + 3] + } + } + } + + return new ImageData(dataNew, widthNew, heightNew) +} + +/** + * calculates mean and stddev for a ndarray tensor + */ +export function tensorStats(tensor) { + const mean = _.sum(tensor.data) / tensor.data.length + const stddev = Math.sqrt(_.sum(tensor.data.map(x => (x - mean) ** 2)) / tensor.data.length) + return { mean, stddev } +} + +/** + * calculates min and max for a ndarray tensor + */ +export function tensorMinMax(tensor) { + let min = Infinity + let max = -Infinity + for (let i = 0, len = tensor.data.length; i < len; i++) { + if (tensor.data[i] < min) min = tensor.data[i] + if (tensor.data[i] > max) max = tensor.data[i] + } + return { min, max } +} + +/** + * Takes in a ndarray of shape [x] + * and creates image data + */ +export function image1Dtensor(tensor) { + const { min, max } = tensorMinMax(tensor) + let imageData = new Uint8ClampedArray(tensor.size * 4) + for (let i = 0, len = imageData.length; i < len; i += 4) { + imageData[i + 3] = 255 * (tensor.data[i / 4] - min) / (max - min) + } + return new ImageData(imageData, tensor.shape[0], 1) +} + +/** + * Takes in a ndarray of shape [x, y] + * and creates image data + */ +export function image2Dtensor(tensor) { + const { min, max } = tensorMinMax(tensor) + let imageData = new Uint8ClampedArray(tensor.size * 4) + for (let i = 0, len = imageData.length; i < len; i += 4) { + imageData[i + 3] = 255 * (tensor.data[i / 4] - min) / (max - min) + } + return new ImageData(imageData, tensor.shape[0], tensor.shape[1]) +} + +/** + * Takes in a TypedArray with size = width * height + * and creates image data + */ +export function image2Darray(arr, width, height, rgb = [0, 0, 0]) { + const size = width * height * 4 + let imageData = new Uint8ClampedArray(size) + for (let i = 0; i < size; i += 4) { + imageData[i] = rgb[0] + imageData[i + 1] = rgb[1] + imageData[i + 2] = rgb[2] + imageData[i + 3] = 255 * arr[i / 4] + } + return new ImageData(imageData, width, height) +} + +/** + * Takes in a ndarray of shape [x, y, z] + * and creates an array of z ImageData [x, y] elements + */ +export function unroll3Dtensor(tensor) { + const { min, max } = tensorMinMax(tensor) + let shape = tensor.shape.slice() + let unrolled = [] + for (let k = 0, channels = shape[2]; k < channels; k++) { + const channelData = _.flatten(unpack(tensor.pick(null, null, k))) + unrolled.push(channelData) + } + + return unrolled.map(channelData => { + let imageData = new Uint8ClampedArray(channelData.length * 4) + for (let i = 0, len = channelData.length; i < len; i++) { + imageData[i * 4] = 0 + imageData[i * 4 + 1] = 0 + imageData[i * 4 + 2] = 0 + imageData[i * 4 + 3] = 255 * (channelData[i] - min) / (max - min) + } + return new ImageData(imageData, shape[0], shape[1]) + }) +} + +/** + * Find top k imagenet classes + */ +export function imagenetClassesTopK(classProbabilities, k = 5) { + const probs = _.isTypedArray(classProbabilities) ? Array.prototype.slice.call(classProbabilities) : classProbabilities + + const sorted = _.reverse(_.sortBy(probs.map((prob, index) => [prob, index]), probIndex => probIndex[0])) + + const topK = _.take(sorted, k).map(probIndex => { + const iClass = imagenetClasses[probIndex[1]] + return { + id: iClass[0], + index: parseInt(probIndex[1], 10), + name: iClass[1].replace(/_/, ' '), + probability: probIndex[0] + } + }) + return topK +} diff --git a/myproj/src/variables.css b/myproj/src/variables.css new file mode 100644 index 0000000000..533d09a8b4 --- /dev/null +++ b/myproj/src/variables.css @@ -0,0 +1,15 @@ +:root { + --color-green: #1bbc9b; + --color-green-light: rgba(27, 188, 155, 0.6); + --color-green-lighter: rgba(27, 188, 155, 0.3); + --color-lightgray: #69707a; + --color-darkgray: #393e46; + --color-yellow: #f5d76e; + --color-red: #f22613; + --color-error: #d24d57; + + --font-sans-serif: 'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; + --font-monospace: 'Share Tech Mono', monospace; + --font-cursive: 'Nothing You Could Do', cursive; +} diff --git a/myproj/test/e2e/custom-assertions/elementCount.js b/myproj/test/e2e/custom-assertions/elementCount.js new file mode 100644 index 0000000000..364e7a469b --- /dev/null +++ b/myproj/test/e2e/custom-assertions/elementCount.js @@ -0,0 +1,27 @@ +// A custom Nightwatch assertion. +// The assertion name is the filename. +// Example usage: +// +// browser.assert.elementCount(selector, count) +// +// For more information on custom assertions see: +// http://nightwatchjs.org/guide#writing-custom-assertions + +exports.assertion = function (selector, count) { + this.message = 'Testing if element <' + selector + '> has count: ' + count + this.expected = count + this.pass = function (val) { + return val === this.expected + } + this.value = function (res) { + return res.value + } + this.command = function (cb) { + var self = this + return this.api.execute(function (selectorToCount) { + return document.querySelectorAll(selectorToCount).length + }, [selector], function (res) { + cb.call(self, res) + }) + } +} diff --git a/myproj/test/e2e/nightwatch.conf.js b/myproj/test/e2e/nightwatch.conf.js new file mode 100644 index 0000000000..f019c0ac44 --- /dev/null +++ b/myproj/test/e2e/nightwatch.conf.js @@ -0,0 +1,46 @@ +require('babel-register') +var config = require('../../config') + +// http://nightwatchjs.org/gettingstarted#settings-file +module.exports = { + src_folders: ['test/e2e/specs'], + output_folder: 'test/e2e/reports', + custom_assertions_path: ['test/e2e/custom-assertions'], + + selenium: { + start_process: true, + server_path: require('selenium-server').path, + host: '127.0.0.1', + port: 4444, + cli_args: { + 'webdriver.chrome.driver': require('chromedriver').path + } + }, + + test_settings: { + default: { + selenium_port: 4444, + selenium_host: 'localhost', + silent: true, + globals: { + devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + javascriptEnabled: true, + acceptSslCerts: true + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + javascriptEnabled: true, + acceptSslCerts: true + } + } + } +} diff --git a/myproj/test/e2e/runner.js b/myproj/test/e2e/runner.js new file mode 100644 index 0000000000..3a02f8e96f --- /dev/null +++ b/myproj/test/e2e/runner.js @@ -0,0 +1,48 @@ +// 1. start the dev server using production config +process.env.NODE_ENV = 'testing' + +const webpack = require('webpack') +const DevServer = require('webpack-dev-server') + +const webpackConfig = require('../../build/webpack.prod.conf') +const devConfigPromise = require('../../build/webpack.dev.conf') + +let server + +devConfigPromise.then(devConfig => { + const devServerOptions = devConfig.devServer + const compiler = webpack(webpackConfig) + server = new DevServer(compiler, devServerOptions) + const port = devServerOptions.port + const host = devServerOptions.host + return server.listen(port, host) +}) +.then(() => { + // 2. run the nightwatch test suite against it + // to run in additional browsers: + // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" + // 2. add it to the --env flag below + // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` + // For more information on Nightwatch's config file, see + // http://nightwatchjs.org/guide#settings-file + let opts = process.argv.slice(2) + if (opts.indexOf('--config') === -1) { + opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) + } + if (opts.indexOf('--env') === -1) { + opts = opts.concat(['--env', 'chrome']) + } + + const spawn = require('cross-spawn') + const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) + + runner.on('exit', function (code) { + server.close() + process.exit(code) + }) + + runner.on('error', function (err) { + server.close() + throw err + }) +}) diff --git a/myproj/test/e2e/specs/test.js b/myproj/test/e2e/specs/test.js new file mode 100644 index 0000000000..a7b1bd920f --- /dev/null +++ b/myproj/test/e2e/specs/test.js @@ -0,0 +1,19 @@ +// For authoring Nightwatch tests, see +// http://nightwatchjs.org/guide#usage + +module.exports = { + 'default e2e tests': function (browser) { + // automatically uses dev Server port from /config.index.js + // default: http://localhost:8080 + // see nightwatch.conf.js + const devServer = browser.globals.devServerURL + + browser + .url(devServer) + .waitForElementVisible('#app', 5000) + .assert.elementPresent('.hello') + .assert.containsText('h1', 'Welcome to Your Vue.js App') + .assert.elementCount('img', 1) + .end() + } +} diff --git a/myproj/test/unit/.eslintrc b/myproj/test/unit/.eslintrc new file mode 100644 index 0000000000..4d5d98f3e6 --- /dev/null +++ b/myproj/test/unit/.eslintrc @@ -0,0 +1,7 @@ +{ + "env": { + "jest": true + }, + "globals": { + } +} diff --git a/myproj/test/unit/jest.conf.js b/myproj/test/unit/jest.conf.js new file mode 100644 index 0000000000..4f7da1519d --- /dev/null +++ b/myproj/test/unit/jest.conf.js @@ -0,0 +1,30 @@ +const path = require('path') + +module.exports = { + rootDir: path.resolve(__dirname, '../../'), + moduleFileExtensions: [ + 'js', + 'json', + 'vue' + ], + moduleNameMapper: { + '^@/(.*)$': '/src/$1' + }, + transform: { + '^.+\\.js$': '/node_modules/babel-jest', + '.*\\.(vue)$': '/node_modules/vue-jest' + }, + testPathIgnorePatterns: [ + '/test/e2e' + ], + snapshotSerializers: ['/node_modules/jest-serializer-vue'], + setupFiles: ['/test/unit/setup'], + mapCoverage: true, + coverageDirectory: '/test/unit/coverage', + collectCoverageFrom: [ + 'src/**/*.{js,vue}', + '!src/main.js', + '!src/router/index.js', + '!**/node_modules/**' + ] +} diff --git a/myproj/test/unit/setup.js b/myproj/test/unit/setup.js new file mode 100644 index 0000000000..edbdbae81e --- /dev/null +++ b/myproj/test/unit/setup.js @@ -0,0 +1,3 @@ +import Vue from 'vue' + +Vue.config.productionTip = false diff --git a/myproj/test/unit/specs/HelloWorld.spec.js b/myproj/test/unit/specs/HelloWorld.spec.js new file mode 100644 index 0000000000..d3e6a58e98 --- /dev/null +++ b/myproj/test/unit/specs/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import Vue from 'vue' +import HelloWorld from '@/components/HelloWorld' + +describe('HelloWorld.vue', () => { + it('should render correct contents', () => { + const Constructor = Vue.extend(HelloWorld) + const vm = new Constructor().$mount() + expect(vm.$el.querySelector('.hello h1').textContent) + .toEqual('Welcome to Your Vue.js App') + }) +}) diff --git a/myproj/webpack.config.js b/myproj/webpack.config.js new file mode 100644 index 0000000000..ea6f996bc9 --- /dev/null +++ b/myproj/webpack.config.js @@ -0,0 +1,71 @@ +'use strict' + +const path = require('path') +const webpack = require('webpack') + +const configExport = { + entry: path.resolve(__dirname, 'src/main'), + + resolve: { extensions: ['.js', '.vue'] }, + output: { + path: path.resolve(__dirname, 'dist'), + publicPath: "/dist/", + filename: 'bundle.min.js' }, + module: { + rules: [ + { + enforce: 'pre', + test: /\.vue$/, + loader: 'eslint-loader', + exclude: /node_modules/ + }, + { + enforce: 'pre', + test: /\.js$/, + loader: 'eslint-loader', + exclude: /node_modules/ + }, + { + test: /\.vue$/, + loader: 'vue-loader', + exclude: /node_modules/ + }, + { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, + { test: /\.css$/, loader: ['style-loader', 'css-loader'] }, + { + test: /\.glsl$/, + loader: 'webpack-glsl-loader' + }, + { + test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, + loader: 'url-loader' + }, + { + test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, + loader: 'url-loader' + }, + { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, + loader: 'url-loader' + } + ] + } +} + +if (process.env.NODE_ENV === 'production') { + configExport.plugins = [ + new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }), + // scope hoisting + new webpack.optimize.ModuleConcatenationPlugin(), + // uglify: unused needs to be set to false or else library will not work properly + new webpack.optimize.UglifyJsPlugin({ + compress: { warnings: false, unused: false }, + output: { comments: false } + }) + ] +} else { + configExport.devtool = 'eval' + configExport.plugins = [new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('development') })] +} + +module.exports = configExport diff --git a/package-lock.json b/package-lock.json index 8ddb17e550..d266e0217b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,744 @@ { - "name": "vue-cli", - "version": "2.9.2", + "name": "kerasjs-lib", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/cli": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.0.0-beta.32.tgz", + "integrity": "sha512-X901Tj60U4gBysqGd8HQfBVPFoDBSAyV8h70rLY1zshOgmKePhnXs6W2pIlx7G1tHd9AJmtzU5PQ5Cwx2y4Upg==", + "dev": true, + "requires": { + "chokidar": "1.7.0", + "commander": "2.12.2", + "convert-source-map": "1.5.1", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.4", + "output-file-sync": "2.0.0", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/code-frame": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.32.tgz", + "integrity": "sha512-EVq4T1a2GviKiQ75OfxNrGPPhJyXzg9jjORuuwhloZbFdrhT4FHa73sv9OFWBwX7rl2b6bxBVmfxrBQYWYz9tA==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "@babel/core": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.0.0-beta.32.tgz", + "integrity": "sha512-IeYWdxmLKYmHtff+fOhWll/Ynnaohpes0KZFuuo49p3KQw7VLFsK+FKyH2btYyx2qaIxrHIMUYtQRZOXCctvLQ==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.32", + "@babel/generator": "7.0.0-beta.32", + "@babel/helpers": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "babylon": "7.0.0-beta.32", + "convert-source-map": "1.5.1", + "debug": "3.1.0", + "json5": "0.5.1", + "lodash": "4.17.4", + "micromatch": "2.3.11", + "resolve": "1.5.0", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.32.tgz", + "integrity": "sha512-JQrG+5JQmaDwyj+VL01eE9dX6PSVBfvDyRbA1AXwzk0+BcQ71++M64K2HzbVyD3sti/yjh0EUJAg0Yw9Fn7ZuQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32", + "jsesc": "2.5.1", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0-beta.32.tgz", + "integrity": "sha512-k7kaUbYARwMPbaSbbC1BqIZFQ8eXUxrzvDmI9JpJGI73ITZCFbO3R8fLkJ3rTAA+VNcBpgCrSFy6hzrkoYRJLA==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.0.0-beta.32.tgz", + "integrity": "sha512-ovdauzFqvO7iU29FLkTMUvo5w8UVyHAkexao6T8/ElxDtqZc6SbbCbgBHO9nl2jqu4gYp0Lo4ggIl1PYDwZMxQ==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-call-delegate": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.0.0-beta.32.tgz", + "integrity": "sha512-lzZt0OolIzd7S7TvUPcJVkmR3GlEPNbkPaoDeVwg0cA9GhhlBoNHVa2OUtzsiSsEGTVaa0hMbNzEYVonHERLaA==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-define-map": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.0.0-beta.32.tgz", + "integrity": "sha512-8zN3+BYcUgi6kdDuMIgZCROQZoziNw89FlBLETzfWXVZLG1GYzIQsazWUvwLxb4FaL9uFLYCfIELAylt473ZIw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.0.0-beta.32.tgz", + "integrity": "sha512-hEttRImD90IVKOabU9uQda3+gOqhA956xvoTgTwTfgiJGDW53ZF5DsYEpg1TO8+P6uZcpgO46nmDEdbi3xUk+A==", + "dev": true, + "requires": { + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.32.tgz", + "integrity": "sha512-ysfIt7p72xm5fjSJsv7fMVN/j+EwIdqu8/MJjt6TqB4wM2r6rFRi0ujBTWDkLGQkRB/P5uDV8qcFCHAHnNzmsg==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.32.tgz", + "integrity": "sha512-bm7lIlizycJQY5SJ3HXWJV4XjSrOt1onzrDcOxUo9FEnKRZDEr/zfi5ar2s5tvvZvve/jGHwZKVKekRw2cjPCQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0-beta.32.tgz", + "integrity": "sha512-mJ+VwjY/0tUHvqKGhSlEpss9OqKbx8tUF7Q89lUSdQvpIoTI91A0mCpNzMrg8Ma03C+aLJ91oa5uPIwHkrAIfA==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.32.tgz", + "integrity": "sha512-9jxfqCBrwCIa0p5ZIy1sakzKKm8x8tn0C52qpPr0M0WJ/k9gpD4ilS/mTV2v0tgmw4agjYdUXQ8slq51/5oOzQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.0.0-beta.32.tgz", + "integrity": "sha512-t1o1EiWVOgB463fplP4QBgDjthQqCWVtOpzp5P5I30FyCUH4XAyNRJyS8+cYxEbGpjM80FKf7IuRmjZhBC8trg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.0.0-beta.32", + "@babel/helper-simple-access": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0-beta.32.tgz", + "integrity": "sha512-7Y6U6biSYJekqXfp3Tv7kbNcZoO5HH7utmUkcpQzBonV8bvp3VyEnJHHsNgz5iJo2OEh7Tdzwapt88Z0j7+0dQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-regex": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0-beta.32.tgz", + "integrity": "sha512-A18MJbDz9azbk4XJVti7VXlcMjxCccpd7hHLzAlLPU8kYWAwUMHgcsnCSp2RsS7rTQky6oCGGjhrphk/Ajn2Lw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.0.0-beta.32.tgz", + "integrity": "sha512-9LC7+/c2ELr6TJD14frREbQFe39oTUHCilmXOA2sgCUALN1JDoWHbFpct0HvCWxeBHkQUzxBFiy5bwah7i2jyQ==", + "dev": true, + "requires": { + "@babel/helper-wrap-function": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-replace-supers": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.0.0-beta.32.tgz", + "integrity": "sha512-zyCvhY2WtD5zAIJs599C+ivbbtpBs6pGeVN0SEf3K1X5VvqjfUvOkc095pGEgdDJnaCNq3zWnOhOlDXI2x59Iw==", + "dev": true, + "requires": { + "@babel/helper-optimise-call-expression": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helper-simple-access": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.0.0-beta.32.tgz", + "integrity": "sha512-wQsW8eA2biFLwCxkRvsJNGRguUJZknkGzAZQO8wwB1uS8mgS9si0F6Bz1VPuB6O5cSF2CPsnT4jWvsat2l2DcQ==", + "dev": true, + "requires": { + "@babel/template": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/helper-wrap-function": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.0.0-beta.32.tgz", + "integrity": "sha512-iyGV+eUxmA20yNEbMm67/0EEaIRGv7g6R06Q4P4PTBye6v6RB6DEOWLw7FiUcl2o+C8VmksDcRtTfeqEe5I1kQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/helpers": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.0.0-beta.32.tgz", + "integrity": "sha512-10qgCPVX3fg8yZ4+BN5iaS4/1owxzm4REpCOXivIWM+Cq1jltekmbkxDdOhHVPMU3SMGBnCsybISzP5be6yHPQ==", + "dev": true, + "requires": { + "@babel/template": "7.0.0-beta.32", + "@babel/traverse": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32" + } + }, + "@babel/plugin-check-constants": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-check-constants/-/plugin-check-constants-7.0.0-beta.32.tgz", + "integrity": "sha512-Ed70DlO8vGoNZcRdQhybK2ENnwVI+nne18vV3wqKYN2ikMUv/ueUOKdZdJ0V0sGhpATeS064UX5HwFD3zu72Jw==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.0.0-beta.32.tgz", + "integrity": "sha512-slu0JQDCcETHJ9teGqc75Lt04XRomWMDeAA9JXJGuKBXlTwq/+rlfK1LQze5M8+/onW9PAr/cqpCZ9Q8bn4j9g==", + "dev": true, + "requires": { + "@babel/helper-remap-async-to-generator": "7.0.0-beta.32", + "@babel/plugin-syntax-async-generators": "7.0.0-beta.32" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.0.0-beta.32.tgz", + "integrity": "sha512-waZLn49DpreTFG1aeZhZQZlZjwltuk5cnZvz1Z2VjHEEQhzznRQqeOEwJLot9HjxvFnS7eQRCzu3QAzQv8FMRQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/plugin-syntax-class-properties": "7.0.0-beta.32" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0-beta.32.tgz", + "integrity": "sha512-l8kaLgrzCdgS3juF57d6xywBYAVxoKJLjffTYym7frGmu7Cc4U1mpPg4kNn2aQS+BleA/7JgBNpvuL4An2L3GQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "7.0.0-beta.32" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0-beta.32.tgz", + "integrity": "sha512-Rkf9P+VInhRJhLA8SPP6XGu5/8DpBXE5x6tiEh5Cn+1R0WvU3B1cNcMcww8XMzT7Jl3B0kDVkU28/+75N7WAqA==", + "dev": true, + "requires": { + "@babel/plugin-syntax-optional-catch-binding": "7.0.0-beta.32" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0-beta.32.tgz", + "integrity": "sha512-8TEs0YpAgbOMclfua/46XZZDtU5AIIx0FgsZrO/ijP9p4XCP93JbPfU8Y6lpSRr8HPm4hPRGFZgwyAuAo0SQ4A==", + "dev": true, + "requires": { + "@babel/helper-regex": "7.0.0-beta.32", + "regexpu-core": "4.1.3" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0-beta.32.tgz", + "integrity": "sha512-FfWnqZ9LsPqTJiYXSOlfoVTBf/WdwZh/tnhXoGAK0Y77ExfcAaJqIqt0QalHHFxLy5uIewgkRilkXTk+qZV2OA==", + "dev": true + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0-beta.32.tgz", + "integrity": "sha512-9PF0kjGQDnpszttGbDuypjqB6rCbu3WTSpBXkCmmgwHmDMXiCXxwAUpZFjrtCgjxVA0q4rVwl2tCfCjVkgBk8w==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0-beta.32.tgz", + "integrity": "sha512-xqXOiFUnziFWIGTqI+tqEU4RL6qTJqpwJh89LoOi+QksH3/YrKvIA7pHUn3Jd0z2QUeZa2XaqTKRjzLX+gmZ+g==", + "dev": true + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0-beta.32.tgz", + "integrity": "sha512-wu8wvUVE3FhnyGY1d1R1sWkgnPwV9pqsHRq/XLZcNIcFwDdUvWWzyCGqkajzvvgFV+9w/QMd2WBcOUsUGXkEFA==", + "dev": true + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0-beta.32.tgz", + "integrity": "sha512-Id82/I8+ZRgQuE6oRRGkgKg1P11eSZ6sNLk20OQQUk3i5u4SGeaagpDiRJ5evgE2gM7ECYfR02yyFmiclOSwVg==", + "dev": true + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.0.0-beta.32.tgz", + "integrity": "sha512-OsQskJJA3GuKECVEzUMQ40b4/ZWZwCQLw3qPN8Dvzl3jJ577JdPRmh38EaDrYhCRv34R9RfdWEWLfaUoYbocLQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "7.0.0-beta.32", + "@babel/helper-remap-async-to-generator": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0-beta.32.tgz", + "integrity": "sha512-Fg6X0h6GF3v9JnO7907Niv5S9maDnPOqtRGoFQvk5CccCOuEya3xdJY/KwvI7eFpygo79CRUzA+dGT6BIJnqHw==", + "dev": true + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0-beta.32.tgz", + "integrity": "sha512-wpgRdXmUk27+ztlhtrQwNsx1CqJgyh30jQZ8MDBpG2vH/+P1rS7ZoKMsNVSu7RvSCuZDusS+Sg9Y7xMs7SnnsQ==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.0.0-beta.32.tgz", + "integrity": "sha512-cgI+ktFC6FKbWI+AGA4/ia2sE/b1AOpFcYk8PpnNAOLp4IS+OtpGqntDVBXvJvnzo/V6+afrh6sl9WrIz3hYpA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "7.0.0-beta.32", + "@babel/helper-define-map": "7.0.0-beta.32", + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/helper-optimise-call-expression": "7.0.0-beta.32", + "@babel/helper-replace-supers": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0-beta.32.tgz", + "integrity": "sha512-xt/hR2r+LEfTvISzCmozUT0DVAh0PfhA+Z++qAnkKg9l/evG4eTkzeVe1mdJdLjCpYlqj2qloxos3L79eYh3rQ==", + "dev": true + }, + "@babel/plugin-transform-destructuring": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.0.0-beta.32.tgz", + "integrity": "sha512-fT0UIbRL4wfUTqHSMMEBVougn48fWm2vjOkB6rBqMt+hdSwarcTs1vcZkol5ZDwLB731ZVJ761Lo2fTWBqDcUQ==", + "dev": true + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0-beta.32.tgz", + "integrity": "sha512-Obktgcju396fmESjnailU4qZnoYbNzQWx7JiRts6/dXFbM6mYfPclUpxy/HuBbn/0oR6qRAMuPrAJPD0yi1+Wg==", + "dev": true + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.0.0-beta.32.tgz", + "integrity": "sha512-Xvyx5BdBL2Y477bDPjmyb4eQoMxoqwW2g2hlwssVfHnvLP0JqM3tMB0RNfAE2XjkIMoBNVUSwVVCbH8XFWEWxg==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0-beta.32.tgz", + "integrity": "sha512-ZtqM+YVsF+AcVo+lFhkjObBrifD/tRFbjHVGCw79Y9imNqn8KIlC2NAN7dcz/G5A5Qn87KYwug5kyJ79PHoeDA==", + "dev": true + }, + "@babel/plugin-transform-function-name": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.0.0-beta.32.tgz", + "integrity": "sha512-+6ZET0e1/kvmgilGpjwGdGNt/7Hmre9vxvhVIw1ztbM+se4iEKP79lceLNA+red22jnlNzRHVo5KzbU7vCNLwA==", + "dev": true, + "requires": { + "@babel/helper-function-name": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0-beta.32.tgz", + "integrity": "sha512-uBXC+JcYALYHkXRZZD49mwD0n1ufWu8lbuHEIjpPvEncp63zklVgV5q1XkhXR7Dm1PWDCuEy8Aj6I0La/PBSmQ==", + "dev": true + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.0.0-beta.32.tgz", + "integrity": "sha512-JmwSwyznAcOsIvgD6uVGA0gB4pAVfn5KveUAKeF/3gWbCmaVtsb8D3N8VEnOmzG9C68/qdPVYs07fFeyyrShCQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.0.0-beta.32.tgz", + "integrity": "sha512-kq2Up4V7l3qdJ3RKiHDyf4hr11uBeBBjf+bi53BcJRtU3/dATSXnJ3UPTWyRs2PVj0geGX61ereyHgP+eUOusA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "7.0.0-beta.32", + "@babel/helper-simple-access": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0-beta.32.tgz", + "integrity": "sha512-JMGVoc03u1BHebJVuDSZ37ZmNAsxsRsVq3rJb7piLOM4k0TTdD0wyAPjNk8+/90kPaFFeP6qhpkUqgAed1Y2Jg==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.0.0-beta.32.tgz", + "integrity": "sha512-z9KLuONpgUz1iBbE2iWCfT1y0GF+aqideaqXlemLg4oqudd52EBfopMMicKh1/2KuIQEG+CQljoURTikanUYww==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0-beta.32.tgz", + "integrity": "sha512-TC0RqzMvCK8A5/kRzrQItS4SiiNOev9Bui861PDNAQBNIJvv2MyPUpOcV5VyCsiGIw4XMDMfcU2DngfzIWq4QQ==", + "dev": true + }, + "@babel/plugin-transform-object-super": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.0.0-beta.32.tgz", + "integrity": "sha512-5rcRZ9fFt8EXSz4r/BdlQi/LlUlCl07RBb0rm3VplAfN/+g1G1rcYCyivXHuhibVkvrdSAMbYZrQv955+WuRtg==", + "dev": true, + "requires": { + "@babel/helper-replace-supers": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.0.0-beta.32.tgz", + "integrity": "sha512-LSp9l0n2Xayn8gidVGunCRtyxEAagSahqZgncw3ERkOrwTNlpfE6eaZTqxp/r2kx6kHYt1md/OIaIAxGhCw0+A==", + "dev": true, + "requires": { + "@babel/helper-call-delegate": "7.0.0-beta.32", + "@babel/helper-get-function-arity": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0-beta.32.tgz", + "integrity": "sha512-AVZFTyFTOk1E5MC3NnSwVh0rWgVLOK2D+DqLVknaAVEU29ZKPKLVgoGJOwEPTQS99GWlRh3yAZ8jGMQT6ZiDpA==", + "dev": true, + "requires": { + "regenerator-transform": "0.11.1" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0-beta.32.tgz", + "integrity": "sha512-oLzdWzXqHrqCfGpFXoetpnaNCAzrqTnEysKYoAgv6f+R3su4y8KXXi80eg0/rTNwZ+i3N3hDC+Ipq5+eSVl4Iw==", + "dev": true + }, + "@babel/plugin-transform-spread": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0-beta.32.tgz", + "integrity": "sha512-e2d+Ee/mn5Kcj/okt+WqyLswuXs3QIgEdXwtN5M9d609y1mCWZN3Bdz7F6HiFoFF5R24dG8nqymRUzbR+Pn2UA==", + "dev": true + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0-beta.32.tgz", + "integrity": "sha512-HvgKJ1j6ziYbphvn7QCvTHk6K/TeqNo3dFdHfv7KgXQYxz/OQV8hxCE4SK6nqesrQftOBWeZlNotexcA8qVRSw==", + "dev": true, + "requires": { + "@babel/helper-regex": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0-beta.32.tgz", + "integrity": "sha512-mUohId4FHet/HxQsJVl9MdakfgxoA5GfE32xSTyZePOZz1kzNVRndx82M7wRSjDqr5Ry9BebTtNagR5Rhd2+EQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "7.0.0-beta.32" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0-beta.32.tgz", + "integrity": "sha512-AILpoMhhFg8el2YZSUIw3sZiy+4wvzDOUBPvbvDlJEjUk2wyZpfsZDv5FzY2LiWeRQxg1Ce06slPzaEMIOxEyw==", + "dev": true + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0-beta.32.tgz", + "integrity": "sha512-paFzs6VyyCxqfuCVVPKe9ASZ50cKaSWwnygmBTZzKt3sdI1YX8KZ4fSgeiqHsR1sIZzJC6oLAiTajMZO8vJyIQ==", + "dev": true, + "requires": { + "@babel/helper-regex": "7.0.0-beta.32", + "regexpu-core": "4.1.3" + } + }, + "@babel/preset-env": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.0.0-beta.32.tgz", + "integrity": "sha512-vzWR4oSse4HhDeB+7KHuY0X0WTrl1w+XBGYvceJby/Q3DuqcRxY+gyw+s82gnjxsh/k+bGwcdkWpnGRQPtDVcw==", + "dev": true, + "requires": { + "@babel/plugin-check-constants": "7.0.0-beta.32", + "@babel/plugin-proposal-async-generator-functions": "7.0.0-beta.32", + "@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.32", + "@babel/plugin-proposal-optional-catch-binding": "7.0.0-beta.32", + "@babel/plugin-proposal-unicode-property-regex": "7.0.0-beta.32", + "@babel/plugin-syntax-async-generators": "7.0.0-beta.32", + "@babel/plugin-syntax-object-rest-spread": "7.0.0-beta.32", + "@babel/plugin-syntax-optional-catch-binding": "7.0.0-beta.32", + "@babel/plugin-transform-arrow-functions": "7.0.0-beta.32", + "@babel/plugin-transform-async-to-generator": "7.0.0-beta.32", + "@babel/plugin-transform-block-scoped-functions": "7.0.0-beta.32", + "@babel/plugin-transform-block-scoping": "7.0.0-beta.32", + "@babel/plugin-transform-classes": "7.0.0-beta.32", + "@babel/plugin-transform-computed-properties": "7.0.0-beta.32", + "@babel/plugin-transform-destructuring": "7.0.0-beta.32", + "@babel/plugin-transform-duplicate-keys": "7.0.0-beta.32", + "@babel/plugin-transform-exponentiation-operator": "7.0.0-beta.32", + "@babel/plugin-transform-for-of": "7.0.0-beta.32", + "@babel/plugin-transform-function-name": "7.0.0-beta.32", + "@babel/plugin-transform-literals": "7.0.0-beta.32", + "@babel/plugin-transform-modules-amd": "7.0.0-beta.32", + "@babel/plugin-transform-modules-commonjs": "7.0.0-beta.32", + "@babel/plugin-transform-modules-systemjs": "7.0.0-beta.32", + "@babel/plugin-transform-modules-umd": "7.0.0-beta.32", + "@babel/plugin-transform-new-target": "7.0.0-beta.32", + "@babel/plugin-transform-object-super": "7.0.0-beta.32", + "@babel/plugin-transform-parameters": "7.0.0-beta.32", + "@babel/plugin-transform-regenerator": "7.0.0-beta.32", + "@babel/plugin-transform-shorthand-properties": "7.0.0-beta.32", + "@babel/plugin-transform-spread": "7.0.0-beta.32", + "@babel/plugin-transform-sticky-regex": "7.0.0-beta.32", + "@babel/plugin-transform-template-literals": "7.0.0-beta.32", + "@babel/plugin-transform-typeof-symbol": "7.0.0-beta.32", + "@babel/plugin-transform-unicode-regex": "7.0.0-beta.32", + "browserslist": "2.9.1", + "invariant": "2.2.2", + "semver": "5.4.1" + } + }, + "@babel/template": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.32.tgz", + "integrity": "sha512-DB9sLgX2mfE29vjAkxHlzLyWr31EO9HaYoAM/UsPSsL70Eudl0i25URwIfQT6S6ckeVFnFP1t6PhERVeV4EAHA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "babylon": "7.0.0-beta.32", + "lodash": "4.17.4" + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.32.tgz", + "integrity": "sha512-dGe2CLduCIZ/iDkbmnqspQguRy5ARvI+zC8TiwFnsJ2YYO2TWK7x2aEwrbkSmi0iPlBP+Syiag7Idc1qNQq74g==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.32", + "@babel/helper-function-name": "7.0.0-beta.32", + "@babel/types": "7.0.0-beta.32", + "babylon": "7.0.0-beta.32", + "debug": "3.1.0", + "globals": "10.4.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-10.4.0.tgz", + "integrity": "sha512-uNUtxIZpGyuaq+5BqGGQHsL4wUlJAXRqOm6g3Y48/CWNGTLONgBibI0lh6lGxjR2HljFYUfszb+mk4WkgMntsA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.32.tgz", + "integrity": "sha512-w8+wzVcYCMb9OfaBfay2Vg5hyj7UfBX6qQtA+kB0qsW1h1NH/7xHMwvTZNqkuFBwjz5wxGS2QmaIcC3HH+UoxA==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + } + }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/inquire": "1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, + "@types/events": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz", + "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw==" + }, + "@types/long": { + "version": "3.0.32", + "resolved": "https://registry.npmjs.org/@types/long/-/long-3.0.32.tgz", + "integrity": "sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA==" + }, + "@types/node": { + "version": "8.0.54", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.54.tgz", + "integrity": "sha512-qetMdTv3Ytz9u9ESLdcYs45LPI0mczYZIbC184n7kY0jczOqPNQsabBfVCh+na3B2shAfvC459JqHV771A8Rxg==", + "requires": { + "@types/events": "1.1.0" + } + }, "absolute": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/absolute/-/absolute-0.0.1.tgz", @@ -12,8 +747,24 @@ "acorn": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", - "dev": true + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==" + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } }, "acorn-jsx": { "version": "3.0.1", @@ -102,6 +853,16 @@ "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, "argparse": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", @@ -110,6 +871,21 @@ "sprintf-js": "1.0.3" } }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", @@ -128,6 +904,12 @@ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -138,6 +920,26 @@ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" }, + "asn1.js": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", + "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -157,6 +959,12 @@ "lodash": "4.17.4" } }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -172,6 +980,15 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "requires": { + "follow-redirects": "1.2.6", + "is-buffer": "1.1.6" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -225,6 +1042,202 @@ } } }, + "babel-eslint": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.0.3.tgz", + "integrity": "sha512-7D4iUpylEiKJPGbeSAlNddGcmA41PadgZ6UAb6JVyh003h3d0EbZusYFBR/+nBgqtaVJM2J2zUVa3N0hrpMH6g==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.31", + "@babel/traverse": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.31.tgz", + "integrity": "sha512-yd7CkUughvHQoEahQqcMdrZw6o/6PwUxiRkfZuVDVHCDe77mysD/suoNyk5mK6phTnRW1kyIbPHyCJgxw++LXg==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.31.tgz", + "integrity": "sha512-c+DAyp8LMm2nzSs2uXEuxp4LYGSUYEyHtU3fU57avFChjsnTmmpWmXj2dv0yUxHTEydgVAv5fIzA+4KJwoqWDA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.31", + "@babel/template": "7.0.0-beta.31", + "@babel/traverse": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.31.tgz", + "integrity": "sha512-m7rVVX/dMLbbB9NCzKYRrrFb0qZxgpmQ4Wv6y7zEsB6skoJHRuXVeb/hAFze79vXBbuD63ci7AVHXzAdZSk9KQ==", + "dev": true, + "requires": { + "@babel/types": "7.0.0-beta.31" + } + }, + "@babel/template": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.31.tgz", + "integrity": "sha512-97IRmLvoDhIDSQkqklVt3UCxJsv0LUEVb/0DzXWtc8Lgiyxj567qZkmTG9aR21CmcJVVIvq2Y/moZj4oEpl5AA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31", + "lodash": "4.17.4" + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.31.tgz", + "integrity": "sha512-3N+VJW+KlezEjFBG7WSYeMyC5kIqVLPb/PGSzCDPFcJrnArluD1GIl7Y3xC7cjKiTq2/JohaLWHVPjJWHlo9Gg==", + "dev": true, + "requires": { + "@babel/code-frame": "7.0.0-beta.31", + "@babel/helper-function-name": "7.0.0-beta.31", + "@babel/types": "7.0.0-beta.31", + "babylon": "7.0.0-beta.31", + "debug": "3.1.0", + "globals": "10.4.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "@babel/types": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.31.tgz", + "integrity": "sha512-exAHB+NeFGxkfQ5dSUD03xl3zYGneeSk2Mw2ldTt/nTvYxuDiuSp3DlxgUBgzbdTFG4fbwPk0WtKWOoTXCmNGg==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + } + }, + "babylon": { + "version": "7.0.0-beta.31", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.31.tgz", + "integrity": "sha512-6lm2mV3S51yEnKmQQNnswoABL1U1H1KHoCCVwdwI3hvIv+W7ya4ki7Aw4o4KxtUHjNKkK5WpZb22rrMMOcJXJQ==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-10.4.0.tgz", + "integrity": "sha512-uNUtxIZpGyuaq+5BqGGQHsL4wUlJAXRqOm6g3Y48/CWNGTLONgBibI0lh6lGxjR2HljFYUfszb+mk4WkgMntsA==", + "dev": true + } + } + }, + "babel-helper-module-imports": { + "version": "7.0.0-beta.3", + "resolved": "https://registry.npmjs.org/babel-helper-module-imports/-/babel-helper-module-imports-7.0.0-beta.3.tgz", + "integrity": "sha512-bdPrIXbUTYfREhRhjbN8SstwQaj0S4+rW4PKi1f2Wc5fizSh0hGYkfXUdiSSOgyTydm956tAyz4FrG61bqdQyw==", + "dev": true, + "requires": { + "babel-types": "7.0.0-beta.3", + "lodash": "4.17.4" + } + }, + "babel-loader": { + "version": "8.0.0-beta.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.0-beta.0.tgz", + "integrity": "sha512-qVXXyIqTrLBH3Ki2VCJog1fUd6qzKUk9lHS34WJPW93Bh0BUvXTFSD5ZkG3a5+Uxxje+RgCk8Y7RyB6zyK9rWw==", + "dev": true, + "requires": { + "find-cache-dir": "1.0.0", + "loader-utils": "1.1.0", + "mkdirp": "0.5.1" + } + }, + "babel-plugin-inline-import": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/babel-plugin-inline-import/-/babel-plugin-inline-import-2.0.6.tgz", + "integrity": "sha1-ijwXlWG1A79K8xnzytQ15reyhjw=", + "dev": true, + "requires": { + "require-resolve": "0.0.2" + } + }, + "babel-plugin-lodash": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-lodash/-/babel-plugin-lodash-3.3.2.tgz", + "integrity": "sha512-lNsptTRfc0FTdW56O087EiKEADVEjJo2frDQ97olMjCKbRZfZPu7MvdyxnZLOoDpuTCtavN8/4Zk65x4gT+C3Q==", + "dev": true, + "requires": { + "babel-helper-module-imports": "7.0.0-beta.3", + "babel-types": "6.26.0", + "glob": "7.1.2", + "lodash": "4.17.4", + "require-package-name": "2.0.1" + }, + "dependencies": { + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.1", + "regenerator-runtime": "0.11.0" + } + }, + "babel-types": { + "version": "7.0.0-beta.3", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-7.0.0-beta.3.tgz", + "integrity": "sha512-36k8J+byAe181OmCMawGhw+DtKO7AwexPVtsPXoMfAkjtZgoCX3bEuHWfdE5sYxRM8dojvtG/+O08M0Z/YDC6w==", + "dev": true, + "requires": { + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "2.0.0" + } + }, + "babylon": { + "version": "7.0.0-beta.32", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.32.tgz", + "integrity": "sha512-PvAmyP2IJEBVAuE5yVzrTSWCCN9VMa1eGns8w3w6FYD/ivHSUmS7n+F40Fmjn+0nCQSUFR96wP0CqQ4jxTnF4Q==", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -244,6 +1257,23 @@ "tweetnacl": "0.14.5" } }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bit-twiddle": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz", + "integrity": "sha1-DGwfq+KyPRcXPZpht7cJPrnhdp4=" + }, "bl": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", @@ -257,6 +1287,12 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, "boom": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", @@ -274,12 +1310,109 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", "dev": true }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.5" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "browserslist": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.9.1.tgz", + "integrity": "sha512-3n3nPdbUqn3nWmsy4PeSQthz2ja1ndpoXta+dwFFNhveGjMg6FXpWYe12vsTpNoXJbzx3j7GZXdtoVIdvh3JbA==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000778", + "electron-to-chromium": "1.3.27" + } + }, "buffer": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", @@ -295,6 +1428,24 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, "builtins": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", @@ -318,8 +1469,13 @@ "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "optional": true + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "caniuse-lite": { + "version": "1.0.30000778", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000778.tgz", + "integrity": "sha1-8efLixOx9nREAikddfC81MMWA2k=", + "dev": true }, "capture-stack-trace": { "version": "1.0.0", @@ -346,7 +1502,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "optional": true, "requires": { "align-text": "0.1.4", "lazy-cache": "1.0.4" @@ -387,6 +1542,32 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -415,7 +1596,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "optional": true, "requires": { "center-align": "0.1.3", "right-align": "0.1.3", @@ -425,8 +1605,7 @@ "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "optional": true + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" } } }, @@ -487,6 +1666,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -500,6 +1685,12 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==" }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -509,7 +1700,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, "requires": { "inherits": "2.0.3", "readable-stream": "2.3.3", @@ -525,6 +1715,15 @@ "proto-list": "1.2.4" } }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, "consolidate": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", @@ -533,17 +1732,77 @@ "bluebird": "3.5.1" } }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, "create-error-class": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", "requires": { - "capture-stack-trace": "1.0.0" + "capture-stack-trace": "1.0.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.9" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" } }, "cross-spawn": { @@ -575,6 +1834,60 @@ } } }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.5", + "randomfill": "1.0.3" + } + }, + "cwise": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/cwise/-/cwise-1.0.10.tgz", + "integrity": "sha1-JO7mBy69/WuMb12tsXCQtkmxK+8=", + "requires": { + "cwise-compiler": "1.1.3", + "cwise-parser": "1.0.3", + "static-module": "1.5.0", + "uglify-js": "2.8.29" + } + }, + "cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "requires": { + "uniq": "1.0.1" + } + }, + "cwise-parser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cwise-parser/-/cwise-parser-1.0.3.tgz", + "integrity": "sha1-jkk8F9VPl8sDCp6YVLyGyd+zVP4=", + "requires": { + "esprima": "1.2.5", + "uniq": "1.0.1" + }, + "dependencies": { + "esprima": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=" + } + } + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -592,6 +1905,12 @@ "assert-plus": "1.0.0" } }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -604,8 +1923,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "optional": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decompress": { "version": "4.2.0", @@ -723,12 +2041,33 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, "diff": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", "dev": true }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.5" + } + }, "doctrine": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz", @@ -756,6 +2095,12 @@ } } }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, "domelementtype": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", @@ -805,6 +2150,42 @@ "rimraf": "2.6.2" } }, + "dup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dup/-/dup-1.0.0.tgz", + "integrity": "sha1-UfxaxoX4GWRp3wuQXpNLIK9bQCk=" + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -819,6 +2200,53 @@ "jsbn": "0.1.1" } }, + "ecstatic": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-2.2.1.tgz", + "integrity": "sha512-ztE4WqheoWLh3wv+HQwy7dACnvNY620coWpa+XqY6R2cVWgaAT2lUISU1Uf7JpdLLJCURktJOaA9av2AOzsyYQ==", + "dev": true, + "requires": { + "he": "1.1.1", + "mime": "1.6.0", + "minimist": "1.2.0", + "url-join": "2.0.2" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "electron-to-chromium": { + "version": "1.3.27", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz", + "integrity": "sha1-eOy4o5kGYYe7N07t412ccFZagD0=", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, "enable": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/enable/-/enable-1.3.2.tgz", @@ -832,12 +2260,42 @@ "once": "1.4.0" } }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, "entities": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", "dev": true }, + "errno": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "dev": true, + "requires": { + "prr": "0.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, "es5-ext": { "version": "0.10.37", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", @@ -913,6 +2371,43 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escodegen": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", + "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", + "requires": { + "esprima": "1.1.1", + "estraverse": "1.5.1", + "esutils": "1.0.0", + "source-map": "0.1.43" + }, + "dependencies": { + "esprima": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", + "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=" + }, + "estraverse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=" + }, + "esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=" + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, "escope": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", @@ -1181,6 +2676,28 @@ "es5-ext": "0.10.37" } }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, "execa": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", @@ -1202,6 +2719,24 @@ "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", "dev": true }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", @@ -1225,11 +2760,38 @@ "tmp": "0.0.33" } }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, + "falafel": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", + "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "requires": { + "acorn": "5.2.1", + "foreach": "2.0.5", + "isarray": "0.0.1", + "object-keys": "1.0.11" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, "fast-deep-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", @@ -1277,6 +2839,12 @@ "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, "filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -1292,6 +2860,39 @@ "trim-repeated": "1.0.0" } }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "make-dir": "1.1.0", + "pkg-dir": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -1304,6 +2905,44 @@ "write": "0.2.1" } }, + "follow-redirects": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.6.tgz", + "integrity": "sha512-FrMqZ/FONtHnbqO651UPpfRUVukIEwJhXMfdr/JWAmrDbeYBu773b1J6gdWDyRIj4hvvzQEHoEOTrdR8o6KLYA==", + "requires": { + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1331,11 +2970,22 @@ "rimraf": "2.6.2" } }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "generate-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", @@ -1351,6 +3001,12 @@ "is-property": "1.0.2" } }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", @@ -1396,6 +3052,25 @@ "path-is-absolute": "1.0.1" } }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", @@ -1494,6 +3169,14 @@ "har-schema": "2.0.0" } }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "requires": { + "function-bind": "1.1.1" + } + }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -1532,6 +3215,25 @@ "has-symbol-support-x": "1.4.1" } }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", @@ -1549,11 +3251,28 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, "htmlparser2": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", @@ -1568,6 +3287,32 @@ "readable-stream": "2.3.3" } }, + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } + }, + "http-server": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.10.0.tgz", + "integrity": "sha1-sqRGsWqduH7TxiK6m+sbCFsSNKc=", + "dev": true, + "requires": { + "colors": "1.0.3", + "corser": "2.0.1", + "ecstatic": "2.2.1", + "http-proxy": "1.16.2", + "opener": "1.4.3", + "optimist": "0.6.1", + "portfinder": "1.0.13", + "union": "0.4.6" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1578,6 +3323,12 @@ "sshpk": "1.13.1" } }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", @@ -1600,6 +3351,12 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1646,26 +3403,100 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, "is": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=" }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, "is-my-json-valid": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", @@ -1683,6 +3514,15 @@ "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, "is-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", @@ -1712,6 +3552,24 @@ "path-is-inside": "1.0.2" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -1768,6 +3626,15 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -1803,6 +3670,18 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -1833,6 +3712,12 @@ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", "dev": true }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, "jsonfile": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", @@ -1883,8 +3768,16 @@ "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "optional": true + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } }, "levn": { "version": "0.3.0", @@ -1896,6 +3789,45 @@ "type-check": "0.3.2" } }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", @@ -2014,11 +3946,25 @@ } } }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", @@ -2049,6 +3995,47 @@ } } }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.4", + "readable-stream": "2.3.3" + } + }, "metalsmith": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/metalsmith/-/metalsmith-2.3.0.tgz", @@ -2109,6 +4096,43 @@ } } }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, "mime-db": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", @@ -2127,6 +4151,18 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2220,8 +4256,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "multimatch": { "version": "2.1.0", @@ -2245,6 +4280,189 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "ndarray": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", + "requires": { + "iota-array": "1.0.0", + "is-buffer": "1.1.6" + } + }, + "ndarray-blas-level1": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ndarray-blas-level1/-/ndarray-blas-level1-1.1.3.tgz", + "integrity": "sha1-7BXPrO2BmH1lGgizcf+3u929eYI=" + }, + "ndarray-blas-level2": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ndarray-blas-level2/-/ndarray-blas-level2-1.1.0.tgz", + "integrity": "sha1-s6YUC5oj/qOg+KE6klwpzP6qzkw=", + "requires": { + "ndarray-blas-level1": "1.1.3" + } + }, + "ndarray-concat-rows": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-concat-rows/-/ndarray-concat-rows-1.0.1.tgz", + "integrity": "sha1-1/h3kmXvw6mniLsU4pf6Hh8CF8M=", + "requires": { + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0", + "util-extend": "1.0.3" + } + }, + "ndarray-fft": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-fft/-/ndarray-fft-1.0.3.tgz", + "integrity": "sha1-3Fu6GOOrgsmXrbrrt455+CyToio=", + "requires": { + "bit-twiddle": "1.0.2", + "cwise": "1.0.10", + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "ndarray-gemm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-gemm/-/ndarray-gemm-1.0.0.tgz", + "integrity": "sha1-POWbMc9eIkPIZfBpQ/e0cUz7se4=" + }, + "ndarray-ops": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ndarray-ops/-/ndarray-ops-1.2.2.tgz", + "integrity": "sha1-WeiNLDKn7ryxvGkPrhQVeVV6YU4=", + "requires": { + "cwise-compiler": "1.1.3" + } + }, + "ndarray-resample": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ndarray-resample/-/ndarray-resample-1.0.1.tgz", + "integrity": "sha1-Qrsz9qS3OMV/9zxgzCINTPx1gh0=", + "requires": { + "cwise": "1.0.10", + "ndarray-fft": "1.0.3", + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0" + } + }, + "ndarray-scratch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ndarray-scratch/-/ndarray-scratch-1.2.0.tgz", + "integrity": "sha1-YwRjbWLrqT20cnrBPGkzQdulDgE=", + "requires": { + "ndarray": "1.0.18", + "ndarray-ops": "1.2.2", + "typedarray-pool": "1.1.0" + } + }, + "ndarray-squeeze": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ndarray-squeeze/-/ndarray-squeeze-1.0.2.tgz", + "integrity": "sha1-diXGnGcMv0YHkuigEd6NBHKU02w=", + "requires": { + "ndarray": "1.0.18" + } + }, + "ndarray-tile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-tile/-/ndarray-tile-1.0.3.tgz", + "integrity": "sha1-eibjlGz43xieqTXHVnmB7Ma4IPo=", + "requires": { + "ndarray-ops": "1.2.2", + "ndarray-scratch": "1.2.0" + } + }, + "ndarray-unpack": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ndarray-unpack/-/ndarray-unpack-1.0.0.tgz", + "integrity": "sha1-S1PHZzAKXjkJuLUiWrVcbohtkdw=", + "requires": { + "cwise": "1.0.10", + "dup": "1.0.0" + } + }, + "ndarray-unsqueeze": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ndarray-unsqueeze/-/ndarray-unsqueeze-1.0.3.tgz", + "integrity": "sha1-3DqNoZx7meukGYgDbeX88pPIqwg=", + "requires": { + "ndarray": "1.0.18" + } + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.1.7", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.3", + "stream-browserify": "2.0.1", + "stream-http": "2.7.2", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.4", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, "npm-conf": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", @@ -2286,6 +4504,26 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-inspect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-0.4.0.tgz", + "integrity": "sha1-9RV8EWwUVbJDsG7pdwM5LFrYn+w=" + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2302,6 +4540,12 @@ "mimic-fn": "1.1.0" } }, + "opener": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", + "dev": true + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -2381,20 +4625,138 @@ } } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + }, + "dependencies": { + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + } + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "output-file-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.0.tgz", + "integrity": "sha1-XTSKGh6u0a0WhkigGi1tEweM6Yc=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "is-plain-obj": "1.1.0", + "mkdirp": "0.5.1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.2", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-extra": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/path-extra/-/path-extra-1.0.3.tgz", + "integrity": "sha1-fBEhiablDVlXkOetIDfkTkEMEWY=", "dev": true }, "path-is-absolute": { @@ -2420,12 +4782,34 @@ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.9" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -2454,12 +4838,40 @@ "pinkie": "2.0.4" } }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "2.1.0" + } + }, "pluralize": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", "dev": true }, + "portfinder": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", + "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", + "dev": true, + "requires": { + "async": "1.5.2", + "debug": "2.6.9", + "mkdirp": "0.5.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -2471,6 +4883,24 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -2487,12 +4917,51 @@ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" }, + "protobufjs": { + "version": "6.8.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.3.tgz", + "integrity": "sha512-/iQhTYnSniRNmdRF9Kvw8odMSokwNOWVDOmMJjW64+EVE6igcdj/82Op/4MJ/WimgMRNac7gChlSVX4Gep/tHg==", + "requires": { + "@protobufjs/aspromise": "1.1.2", + "@protobufjs/base64": "1.1.2", + "@protobufjs/codegen": "2.0.4", + "@protobufjs/eventemitter": "1.1.0", + "@protobufjs/fetch": "1.1.0", + "@protobufjs/float": "1.0.2", + "@protobufjs/inquire": "1.1.0", + "@protobufjs/path": "1.1.2", + "@protobufjs/pool": "1.1.0", + "@protobufjs/utf8": "1.1.0", + "@types/long": "3.0.32", + "@types/node": "8.0.54", + "long": "3.2.0" + } + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "dev": true + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.5" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -2503,6 +4972,87 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "quote-stream": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-0.0.0.tgz", + "integrity": "sha1-zeKelMQJsW4Z3HCYuJtmWPlyHTs=", + "requires": { + "minimist": "0.0.8", + "through2": "0.4.2" + } + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", + "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", + "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "dev": true, + "requires": { + "randombytes": "2.0.5", + "safe-buffer": "5.1.1" + } + }, "read-metadata": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-metadata/-/read-metadata-1.0.0.tgz", @@ -2511,6 +5061,27 @@ "yaml-js": "0.0.8" } }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", @@ -2525,6 +5096,18 @@ "util-deprecate": "1.0.2" } }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } + }, "readline2": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", @@ -2580,6 +5163,95 @@ } } }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-5.1.3.tgz", + "integrity": "sha512-Yjy6t7jFQczDhYE+WVm7pg6gWYE258q4sUkk9qDErwXJIqx7jU9jGrMFHutJK/SRfcg7MEkXjGaYiVlOZyev/A==", + "dev": true, + "requires": { + "regenerate": "1.3.3" + } + }, + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "dev": true + }, + "regenerator-transform": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.11.1.tgz", + "integrity": "sha512-q8SAPMEyARQHzyXNWNrlz5oNnI6k4yo8ncEcvH1aXjUCqyVQ7TeV/AttqBLcySCReXVk/+fUydo/RaEIAOnRfA==", + "dev": true, + "requires": { + "babel-types": "7.0.0-beta.3", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regexpu-core": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.1.3.tgz", + "integrity": "sha512-mB+njEzO7oezA57IbQxxd6fVPOeWKDmnGvJ485CwmfNchjHe5jWwqKepapmzUEj41yxIAqOg+C4LbXuJlkiO8A==", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regenerate-unicode-properties": "5.1.3", + "regjsgen": "0.3.0", + "regjsparser": "0.2.1", + "unicode-match-property-ecmascript": "1.0.3", + "unicode-match-property-value-ecmascript": "1.0.1" + } + }, + "regjsgen": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.3.0.tgz", + "integrity": "sha1-DuSj6SdkMM2iXx54nqbBW4ewy0M=", + "dev": true + }, + "regjsparser": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.2.1.tgz", + "integrity": "sha1-w3h1U/rwTndcMCEC7zRtmVAA7Bw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -2614,6 +5286,33 @@ "uuid": "3.1.0" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "require-package-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", + "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=", + "dev": true + }, + "require-resolve": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/require-resolve/-/require-resolve-0.0.2.tgz", + "integrity": "sha1-urQQqxruLz9Vt5MXRR3TQodk5vM=", + "dev": true, + "requires": { + "x-path": "0.0.2" + } + }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -2624,6 +5323,12 @@ "resolve-from": "1.0.1" } }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", @@ -2652,7 +5357,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "optional": true, "requires": { "align-text": "0.1.4" } @@ -2665,6 +5369,16 @@ "glob": "7.1.2" } }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -2714,6 +5428,39 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz", + "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -2745,6 +5492,12 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", @@ -2759,6 +5512,12 @@ "hoek": "4.2.0" } }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", @@ -2767,6 +5526,27 @@ "amdefine": "1.0.1" } }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -2787,11 +5567,105 @@ "tweetnacl": "0.14.5" } }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=" - }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=" + }, + "static-eval": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-0.2.4.tgz", + "integrity": "sha1-t9NNg4k3uWn5ZBygfUj47eJj6ns=", + "requires": { + "escodegen": "0.0.28" + }, + "dependencies": { + "escodegen": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.28.tgz", + "integrity": "sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=", + "requires": { + "esprima": "1.0.4", + "estraverse": "1.3.2", + "source-map": "0.4.4" + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + }, + "estraverse": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", + "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=" + } + } + }, + "static-module": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-1.5.0.tgz", + "integrity": "sha1-J9qYg8QajNCSNvhC8MHrxu32PYY=", + "requires": { + "concat-stream": "1.6.0", + "duplexer2": "0.0.2", + "escodegen": "1.3.3", + "falafel": "2.1.0", + "has": "1.0.1", + "object-inspect": "0.4.0", + "quote-stream": "0.0.0", + "readable-stream": "1.0.34", + "shallow-copy": "0.0.1", + "static-eval": "0.2.4", + "through2": "0.4.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "stream-http": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", + "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -2936,6 +5810,12 @@ } } }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, "tar-stream": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", @@ -2958,6 +5838,51 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, + "through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, "thunkify": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", @@ -2984,6 +5909,15 @@ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, + "timers-browserify": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.4.tgz", + "integrity": "sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -2992,6 +5926,18 @@ "os-tmpdir": "1.0.2" } }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, "toml": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.3.tgz", @@ -3013,12 +5959,24 @@ "escape-string-regexp": "1.0.5" } }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, "tryit": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", "dev": true }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -3051,14 +6009,21 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/typedarray-pool/-/typedarray-pool-1.1.0.tgz", + "integrity": "sha1-0RT0hIAUifU+yrXoCIqiMET0mNk=", + "requires": { + "bit-twiddle": "1.0.2", + "dup": "1.0.0" + } }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "optional": true, "requires": { "source-map": "0.5.7", "uglify-to-browserify": "1.0.2", @@ -3068,8 +6033,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "optional": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -3079,6 +6043,25 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "optional": true }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "uid": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/uid/-/uid-0.0.2.tgz", @@ -3093,6 +6076,56 @@ "through": "2.3.8" } }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.3.tgz", + "integrity": "sha512-iG/2t0F2LAU8aZYPkX5gi7ebukHnr3sWFESpb+zPQeeaQwOkfoO6ZW17YX7MdRPNG9pCy+tjzGill+Ah0Em0HA==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.3.tgz", + "integrity": "sha512-nFcaBFcr08UQNF15ZgI5ISh3yUnQm7SJRRxwYrL5VYX46pS+6Q7TCTv4zbK+j6/l7rQt0mMiTL2zpmeygny6rA==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "1.0.3", + "unicode-property-aliases-ecmascript": "1.0.3" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.1.tgz", + "integrity": "sha512-lM8B0FDZQh9yYGgiabRQcyWicB27VLOolSBRIxsO7FeQPtg+79Oe7sC8Mzr8BObDs+G9CeYmC/shHo6OggNEog==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.3.tgz", + "integrity": "sha512-TdDmDOTxEf2ad1g3ZBpM6cqKIb2nJpVlz1Q++casDryKz18tpeMBhSng9hjC1CTQCkOV9Rw2knlSB6iRo7ad1w==", + "dev": true + }, + "union": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", + "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", + "dev": true, + "requires": { + "qs": "2.3.3" + }, + "dependencies": { + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, "unyield": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/unyield/-/unyield-0.0.1.tgz", @@ -3106,6 +6139,30 @@ "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-join": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.2.tgz", + "integrity": "sha1-wHJ1aWetJLi1nldBVRyqx49QuLc=", + "dev": true + }, "url-parse-lax": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", @@ -3127,16 +6184,48 @@ "os-homedir": "1.0.2" } }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "util-extend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" + }, "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, "validate-npm-package-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", @@ -3155,6 +6244,15 @@ "extsprintf": "1.3.0" } }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, "ware": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", @@ -3163,6 +6261,154 @@ "wrap-fn": "0.1.5" } }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + } + }, + "webpack": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.9.1.tgz", + "integrity": "sha512-jONJ0l8nqgiQVkqs15O9TFWLozbFkCgVodVrBXBK/PIBFeGkaOGo30Ov57iQqYRwAWNDM5vyLPZYmAIpPa5QSw==", + "dev": true, + "requires": { + "acorn": "5.2.1", + "acorn-dynamic-import": "2.0.2", + "ajv": "5.5.0", + "ajv-keywords": "2.1.1", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + } + } + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", @@ -3172,6 +6418,12 @@ "isexe": "2.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, "win-fork": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/win-fork/-/win-fork-1.1.1.tgz", @@ -3180,14 +6432,60 @@ "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "optional": true + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, "wrap-fn": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", @@ -3210,11 +6508,26 @@ "mkdirp": "0.5.1" } }, + "x-path": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/x-path/-/x-path-0.0.2.tgz", + "integrity": "sha1-KU0Ha7l6dwbMBwu7Km/YxU32exI=", + "dev": true, + "requires": { + "path-extra": "1.0.3" + } + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", @@ -3230,7 +6543,6 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "optional": true, "requires": { "camelcase": "1.2.1", "cliui": "2.1.0", @@ -3238,6 +6550,23 @@ "window-size": "0.1.0" } }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, "yauzl": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", diff --git a/package.json b/package.json index 982a300a29..d8003a019a 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,9 @@ { - "name": "vue-cli", - "version": "2.9.2", + "name": "kerasjs-lib", + "version": "1.0.0", "description": "A simple CLI for scaffolding Vue.js projects.", "preferGlobal": true, + "main": "src/", "bin": { "vue": "bin/vue", "vue-init": "bin/vue-init", @@ -17,13 +18,18 @@ "cli", "spa" ], - "author": "Evan You", + "author": "BL", "license": "MIT", "bugs": { "url": "https://github.com/vuejs/vue-cli/issues" }, "homepage": "https://github.com/vuejs/vue-cli#readme", "scripts": { + "build:browser": "rm -rf dist; NODE_ENV=production BABEL_ENV=browser webpack --config webpack.config.js", + "build:node": "rm -rf lib; NODE_ENV=production BABEL_ENV=node babel src --out-dir lib", + "build": "npm run build:browser && npm run build:node", + "myproj:build": "cd myproj; rm -rf dist; NODE_ENV=production BABEL_ENV=browser webpack --config webpack.config.js", + "myproj:server": "cd myproj; http-server . -c-1 -p 8080", "test": "npm run lint && npm run e2e", "lint": "eslint test/e2e/test*.js lib bin/* --env mocha", "e2e": "rimraf test/e2e/mock-template-build && mocha test/e2e/test.js --slow 1000" @@ -48,16 +54,48 @@ "uid": "0.0.2", "user-home": "^2.0.0", "validate-npm-package-name": "^3.0.0", - "coffee-script": "1.12.7" + "coffee-script": "1.12.7", + "axios": "^0.17.1", + "bluebird": "^3.5.1", + "cwise": "^1.0.10", + "lodash": "^4.17.4", + "ndarray": "^1.0.18", + "ndarray-blas-level2": "^1.1.0", + "ndarray-concat-rows": "^1.0.1", + "ndarray-gemm": "^1.0.0", + "ndarray-ops": "^1.2.2", + "ndarray-resample": "^1.0.1", + "ndarray-squeeze": "^1.0.2", + "ndarray-tile": "^1.0.3", + "ndarray-unpack": "^1.0.0", + "ndarray-unsqueeze": "^1.0.3", + "performance-now": "^2.1.0", + "protobufjs": "^6.8.1" }, "devDependencies": { + "@babel/cli": "7.0.0-beta.32", + "@babel/core": "7.0.0-beta.32", + "@babel/plugin-proposal-class-properties": "7.0.0-beta.32", + "@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.32", + "@babel/preset-env": "7.0.0-beta.32", + "babel-eslint": "^8.0.2", + "babel-loader": "8.0.0-beta.0", + "babel-plugin-inline-import": "^2.0.6", + "babel-plugin-lodash": "^3.3.2", "chai": "^4.1.2", "eslint": "^3.19.0", "eslint-plugin-vue-libs": "^1.2.1", "execa": "^0.8.0", - "mocha": "^3.5.3" + "http-server": "^0.10.0", + "mocha": "^3.5.3", + "webpack": "^3.8.1" }, "engines": { "node": ">=6.0.0" + }, + "directories": { + "doc": "docs", + "lib": "lib", + "test": "test" } }